Skip to main content
11mo ago

Rive file resolution issue

Hi, I'm working on a page that loads Rive files when they become visible on the screen. I'm doing this by loading the file only after a certain tab is clicked or by using an observer. The Rive files act as a lightbox, where clicking on a thumbnail opens a modal displaying a larger version of the Rive file. However, I'm having an issue with the resolution of the smaller/thumbnail version. It's the same file as the one in the modal popup, but the modal version is much crisper.

Site link : https://tangolanding.webflow.io/how-tango-delivers-on-ease-of-use
Loom Video : https://www.loom.com/share/7e5a53b650bf473c9a84f4183a13b12d?sid=26c81ecd-49a9-45a9-9cb1-429d05d8d7fe

Code Snippet:
document.addEventListener("DOMContentLoaded", function() {

const rivFiles = [

"https://prod-tango-public-assets.s3.amazonaws.com/capture.riv",

"https://prod-tango-public-assets.s3.amazonaws.com/confetti.riv",

"https://prod-tango-public-assets.s3.amazonaws.com/guidance.riv",

"https://prod-tango-public-assets.s3.amazonaws.com/pin-a-tango.riv"

];

const loadRivTab = document.querySelectorAll('[data-load-riv]');

loadRivTab.forEach(tab => {

tab.addEventListener('click', () => {

let idx = tab.getAttribute('data-load-riv');

if (idx == 1) {

const clickCreate3 = new rive.Rive({

src: rivFiles[idx],

canvas: document.getElementById("clickCreate3"),

autoplay: true,

stateMachines: "State Machine 1",

onLoad: () => {

clickCreate3.resizeDrawingSurfaceToCanvas();

},

});

} else if (idx == 2) {

const guide2 = new rive.Rive({

src: rivFiles[idx],

canvas: document.getElementById("guide2"),

autoplay: true,

stateMachines: "State Machine 1",

onLoad: () => {

guide2.resizeDrawingSurfaceToCanvas();

},

});

} else if (idx == 3) {

const guide3 = new rive.Rive({

src: rivFiles[idx],

canvas: document.getElementById("guide3"),

autoplay: true,

stateMachines: "State Machine 1",

onLoad: () => {

guide3.resizeDrawingSurfaceToCanvas();

},

});

}

});

});

function isElementFullyVisible(el) {

const rect = el.getBoundingClientRect();

return (

rect.top >= 0 &&

rect.left >= 0 &&

rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&

rect.right <= (window.innerWidth || document.documentElement.clientWidth)

);

}

// Using Intersection Observer API

const observer = new IntersectionObserver((entries, observer) => {

entries.forEach(entry => {

if (entry.isIntersecting) {

const clickCreate1 = new rive.Rive({

src: rivFiles[0],

canvas: document.getElementById("clickCreate1"),

autoplay: true,

stateMachines: "State Machine 1",

onLoad: () => {

clickCreate1.resizeDrawingSurfaceToCanvas();

},

});

observer.unobserve(entry.target);

}

});

});

const element = document.getElementById("clickCreate1");

if (element) {

observer.observe(element);

}

// modal

const modalOpen = document.querySelectorAll('[data-modal-open]');

const modalComponent = document.querySelector('[data-modal-component]');

const modalClose = document.querySelectorAll('[data-modal-close]')

let modal;

modalOpen.forEach(modal => {

modal.addEventListener('click', function(){

modalComponent.style.display = 'flex'

modal = new rive.Rive({

src: rivFiles[this.getAttribute('data-modal-open')],

canvas: document.getElementById("modalPopup"),

autoplay: true,

stateMachines: "State Machine 1",

onLoad: () => {

modal.resizeDrawingSurfaceToCanvas();

},

});

})

})

modalClose.forEach(modal =>{

modal.addEventListener('click', function(){

modalComponent.style.display = 'none'

})

})

// Custom tabs initialization function

function initializeTabs() {

const customTabWrappers = document.querySelectorAll('[data-div="custom-tab"]');

customTabWrappers.forEach(wrapper => {

const tabsNav = wrapper.querySelectorAll('[data-tab-nav]');

const tabsContent = wrapper.querySelectorAll('[data-tab-content]');

// Hide all tabs initially

tabsContent.forEach(tab => { tab.style.display = 'none'; });

// Show the first tab by default

if (tabsContent.length > 0) {

tabsContent[0].style.display = 'block';

tabsNav[0].classList.add('is-current');

}

tabsNav.forEach(nav => {

nav.addEventListener('click', function() {

const tab = this.getAttribute('data-tab-nav');

// Hide all tabs and remove all active states

tabsContent.forEach(content => { content.style.display = 'none'; });

tabsNav.forEach(navbar => navbar.classList.remove('is-current'));

// Show the selected tab

this.classList.add('is-current');

wrapper.querySelector(`[data-tab-content="${tab}"]`).style.display = 'block';

});

});

});

}

initializeTabs();

});

1 reply
11mo ago

Hi! there might be several reasons why the small thumbnail looks like that.
I tried accessing the site link but it's password protected.
My guess without looking at the html, is that the canvas used as a thumbnail has its width and height set to the size of the large resolution.
So, once Rive renders in that canvas, the browser scales the canvas element and since it doesn't differentiate between what is text and what is not, it simply drops pixels it can't render.