I have this spinning globe animation from AMcharts on the front page of my site. but it eats a LOT of system resources, even when its scrolled off screen, any more animated buttons added to the site will make chrome slow to a crawl. I have done some research over the last couple of days about how to stop and start three.js animations, and canvas animations and found out about intersection observer, and I copied and pasted some code from places that I've found it and added it in, it seems like I'm still missing the actual stop and start functions from AMcharts that intersectionobserver can hook on to to control the animation while intersecting with my div with the id="status"
I've studied the AMcharts docs but I can't make any sense of it, is there a stop and start or pause function in amcharts?
/**
* ---------------------------------------
* This demo was created using amCharts 4.
*
* For more information visit:
* https://www.amcharts.com/
*
* Documentation is available at:
* https://www.amcharts.com/docs/v4/
* ---------------------------------------
*/
// Themes begin
am4core.useTheme(am4themes_animated);
// Themes end
am4core.options.queue = true;
am4core.options.onlyShowOnViewport = true;
var chart = am4core.create("chartdiv", am4maps.MapChart);
// Set map definition
chart.geodata = am4geodata_worldLow;
// Set projection
chart.projection = new am4maps.projections.Orthographic();
chart.panBehavior = "none";
chart.deltaLatitude = -20;
chart.padding(20,20,20,20);
// Create map polygon series
var polygonSeries = chart.series.push(new am4maps.MapPolygonSeries());
// Make map load polygon (like country names) data from GeoJSON
polygonSeries.useGeodata = true;
//polygonSeries.include = ["BR", "UA", "MX", "CI"];
// Configure series
var polygonTemplate = polygonSeries.mapPolygons.template;
polygonTemplate.fill = am4core.color("#d5ebfe");
polygonTemplate.stroke = am4core.color("#fff");
polygonTemplate.strokeWidth = 0.0;
var graticuleSeries = chart.series.push(new am4maps.GraticuleSeries());
graticuleSeries.mapLines.template.line.stroke = am4core.color("#00000");
graticuleSeries.mapLines.template.line.strokeOpacity = 0.00;
graticuleSeries.fitExtent = false;
chart.maxZoomLevel = 1;
chart.backgroundSeries.mapPolygons.template.polygon.fillOpacity = 0.0;
chart.backgroundSeries.mapPolygons.template.polygon.fill = am4core.color("#ffffff");
// Create hover state and set alternative fill color
let animation;
setTimeout(function(){
animation = chart.animate({property:"deltaLongitude", to:100000}, 20000000);
}, 3000)
chart.seriesContainer.events.on("down", function(){
// animation.stop();
})
////////////////My added intersectionObserver code////////
function start() {
create();
}
// stop render
function stop() {
window.cancelAnimationFrame(requestId);
requestId = undefined;
}
const statusElem = document.querySelector('.status');
const onScreen = new Set();
const intersectionObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
onScreen.add(entry.target);
start();
console.log('render has been started');
} else {
onScreen.delete(entry.target);
stop();
console.log('render has been halted');
}
});
statusElem.textContent = onScreen.size
? `on screen: ${[...onScreen].map(e => e.textContent).join(', ')}`
: 'none';
});
document.querySelectorAll('#chartdiv').forEach(elem => intersectionObserver.observe(elem));
.status {
position: fixed;
background: rgba(0,0,0,0.8);
color: white;
padding: 1em;
font-size: medium;
top: 50%;
left: 0;
z-index: 998;
}
#header{
position:fixed;
top: 0px;
right:0px;
z-index: 998;
height: 5em;
width: 100%;
background-color: white;
opacity: 80%;
}
#chartdiv {
width: 100%;
height: 20em;
max-width:100%;
}
#section0{
background-image: linear-gradient(128deg,#340191,#000);
height: 300vh;
}
<body>
<script src="https://www.amcharts.com/lib/4/core.js"></script>
<script src="https://www.amcharts.com/lib/4/maps.js"></script>
<script src="https://www.amcharts.com/lib/4/geodata/worldLow.js"></script>
<script src="https://www.amcharts.com/lib/4/themes/animated.js"></script>
<div class="status"></div>
<header id="header">
</header>
<div class="status">status</div>
<div class="section" id="section0">
<div class="intro">
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<div id="chartdiv"></div>
<script src="js/globe.js"></script>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
</div>
</div>
</body>
There is the minimum reproduceable example. when #status intersects with #chartdiv the animation should run, when it doesn't the animation should stop.
Animation Class have two methods that you can utilize here:
pause()
andresume()
More information in Docs: https://www.amcharts.com/docs/v4/reference/animation/