Auto Scroll Text Horizontally for long song names

Hello There,
I love the audio player, I don’t use it for music but for Sound Audio Demos and I have found
the text does truncate, would be great if (we use) a more long texts, it auto-scroll horizontally instead of simply truncate, this happens too for songs that uses long song tittles.

Beside that, I love the rest of the player, thank you in advance!

2 Likes

Hi there, @Antonio_Blanca and welcome to the Community :wave:

Will this type of animation work for you?

1 Like

Hi Max,

Thanks a lot for looking into this. That would be awesome!

1 Like

Got it!

I’ve passed your request on to the devs and will let you know once the solution is ready :slightly_smiling_face:

2 Likes

Great, many thanks Max!

Is there any bit of code that I could add meanwhile? I have this player for a product audio demo and this truncated text doesn’t allow to the potential buyers understand the sound context.

Thanks once more again!

2 Likes

Unfortunately, we don’t have a ready code at the moment, but we’ll try to create it for you as soon as possible :slightly_smiling_face:

2 Likes

Sure! I understand and I appreciate it.

Thanks a lot for adding this!

1 Like

Hi there, @Antonio_Blanca :waving_hand:

Thank you for waiting!

We’ve added this code to the Custom JS field on the Style tab of your widget’s settings:

const CONFIG = {
  mobile: {
    target: '[class*="Mobile__StyledPlaylist-sc"]',
    author: '[class*="Mobile__Author-sc"]',
    playlistItem: '[class*="PlaylistItem__Author-sc"]'
  },
  desktop: {
    target: '[class*="FloatingBar__StyledPlaylist-sc"]',
    author: '[class*="Bar__Author-sc"]',
    playlistItem: '[class*="PlaylistItem__Author-sc"]'
  },
  speed: 30,
  delay: 1000,
  offset: [0, 0.1, 0.8]
};

function listener(selector, callback) {
  const firstTarget = document.querySelector(selector);
  if (firstTarget) {
    return callback(firstTarget);
  }

  const observer = new MutationObserver((_, observer) => {
    const targetNode = document.querySelector(selector);
    if (targetNode) {
      observer.disconnect();
      callback(targetNode);
    }
  });
  observer.observe(document.body, { childList: true, subtree: true });
}

const animationsMap = new WeakMap();

function animateBlock(block) {
  const existingAnimation = animationsMap.get(block);
  existingAnimation?.cancel();

  block.style.removeProperty('overflow');
  block.style.removeProperty('whiteSpace');
  block.style.removeProperty('display');

  const scrollWidth = block.scrollWidth;
  const clientWidth = block.clientWidth;

  if (scrollWidth > clientWidth) {
    block.style.overflow = 'unset';
    block.style.whiteSpace = 'nowrap';
    block.style.display = 'inline-block';

    const distance = scrollWidth - clientWidth;
    const dynamicDuration = Math.ceil(distance / CONFIG.speed) * 1000;

    const keyframes = {
      transform: [
        'translateX(0px)',
        'translateX(0px)',
        `translateX(-${scrollWidth - clientWidth}px)`,
        `translateX(-${scrollWidth - clientWidth}px)`
      ],
      offset: CONFIG.offset
    };

    const options = {
      iterations: Infinity,
      duration: dynamicDuration,
      delay: CONFIG.delay
    };

    const animation = block.animate(keyframes, options);
    animationsMap.set(block, animation);
  }
}

const device = window.innerWidth < 768 ? 'mobile' : 'desktop';
const { target, author, playlistItem } = CONFIG[device];

listener(target, () => {
  const authors = document.querySelectorAll(author);
  const playlistItems = document.querySelectorAll(playlistItem);

  [...authors, ...playlistItems].forEach(animateBlock);

  const mutationObserver = new MutationObserver(([{ target }]) => {
    animateBlock(target.parentNode);
  });
  mutationObserver.observe(document.querySelector(author), {
    characterData: true,
    subtree: true
  });
});

CONFIG speed setting in the code lets you adjust the animation speed in milliseconds

And the delay option sets the animation delay on the first load (in milliseconds)


Please check it out and let me know if you like the result :wink:

1 Like

Hi Max!

Awesome, it works great. <3

I appreciate it a lot, thanks once again!

1 Like

Perfect! We’re always here to help if anything else comes up :slightly_smiling_face: