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();
});
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.