Lightning Aura Components Performance – Load All Necessary Images on Init

I have a lightning component that displays an image of the US map. The map is divided into 13 different regions based on a criteria. I am using image map to identify different regions on the map. Now when a user hovers on one of these regions, i replace the underlying image so that the user can see a visual cue that the region is selected.

All this is working great. But, since i have 13 regions i have 13 different images, one in which each of the 13 regions is selected, the image swapping has a little bit of a delay for the first time. Once i have moved my mouse over all the 13 regions, it is super fast after that.

So, my question is, is there any way to load all the 13 images when the component is initialized so all the images are available in the cache for immediate hot swap on hover.

Note: the images are available as a static resource in a zip file.

edit: I do understand that this going to increase the initial load time of the component, but i realize that is a trade off i need to make to ensure fluid user experience after the page loads.

Here is the code for my component, if it helps.

Component:

    <aura:component implements="flexipage:availableForAllPageTypes,force:appHostable">
    <ltng:require styles="{!$Resource.SLDS231 + '/assets/styles/salesforce-lightning-design-system.css'}" />
    <ltng:require scripts="{!$Resource.Jquery + '/jquery-3.2.1.min.js'}" />
    <ltng:require scripts="{!$Resource.ImageMapster + '/jquery.imagemapster.js'}" />
    <ltng:require scripts="{!$Resource.ImageResizer + '/ImageResizer/imageMapResizer.min.js'}" afterScriptsLoaded="{!c.mapResizer}"/>
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    <aura:attribute name="displayImage" type="string" />
    <aura:attribute name="staticImage" type="string" />
    <aura:registerEvent name="regionChangedEvent" type="c:RegionChanged"/>

    <div id="map">
        <img id="mapImage" style="width:466;height:445" src="{!v.displayImage}" usemap="#region-map" displaymode="Original" title="region-map"  />
        <map id="region-map" name="region-map">
            <area id="region-1" onclick="{!c.select}" onmouseenter="{!c.mouseEnter}"  onmouseleave="{!c.mouseLeave}" data-region="region-1" title="Region 1" shape="poly" coords="373,325,388,317,382,308,397,293,389,276,380,279,368,296" />
            <area id="region-2" onclick="{!c.select}" onmouseenter="{!c.mouseEnter}"  onmouseleave="{!c.mouseLeave}" data-region="region-2" title="Region 2" shape="poly" coords="337,322,342,313,354,312,354,305,366,296,371,322,367,334,347,337,357,331,350,322" />
            <area id="region-3" onclick="{!c.select}" onmouseenter="{!c.mouseEnter}"  onmouseleave="{!c.mouseLeave}" data-region="region-3" title="Region 3" shape="poly" coords="332,356,341,345,348,336,353,327,345,321,330,327,322,330,315,327,325,322,321,314,315,303,302,308,304,320,297,332,299,342,307,358" />
            <area id="region-4" onclick="{!c.select}" onmouseenter="{!c.mouseEnter}"  onmouseleave="{!c.mouseLeave}" data-region="region-4" title="Region 4" shape="poly" coords="280,390,274,375,279,361,286,369,305,359,300,350,293,347,298,337,296,326,286,321,276,326,278,338,257,337,252,343,224,340,223,335,188,330,183,357,251,362,256,355,265,360,261,366,263,389" />
            <area id="region-5" onclick="{!c.select}" onmouseenter="{!c.mouseEnter}"  onmouseleave="{!c.mouseLeave}" data-region="region-5" title="Region 5" shape="poly" coords="277,380,275,371,276,362,287,367,297,367,310,358,332,355,337,347,348,336,359,337,361,354,364,367,347,383,337,398,342,416,349,436,345,441,335,433,332,425,329,416,322,409,307,409,297,409,289,404,293,390,280,392" />
            <area id="region-6" onclick="{!c.select}" onmouseenter="{!c.mouseEnter}"  onmouseleave="{!c.mouseLeave}" data-region="region-6" title="Region 6" shape="poly" coords="178,394,183,356,260,359,261,386,287,389,292,399,284,417,261,410,244,423,246,441,230,433,223,419,215,409,209,416,200,404,190,393" />
            <area id="region-7" onclick="{!c.select}" onmouseenter="{!c.mouseEnter}"  onmouseleave="{!c.mouseLeave}" data-region="region-7" title="Region 7" shape="poly" coords="222,338,254,342,254,339,273,337,274,343,281,335,279,324,294,322,295,315,300,301,313,298,304,293,293,296,293,291,279,296,272,294,282,287,259,277,219,277,216,294,227,295" />
            <area id="region-9" onclick="{!c.select}" onmouseenter="{!c.mouseEnter}"  onmouseleave="{!c.mouseLeave}" data-region="region-9" title="Region 9" shape="poly" coords="109,306,144,315,142,321,151,323,150,329,158,332,154,350,182,356,177,395,143,381,134,380,126,398,144,409,149,418,140,421,139,415,129,407,116,404,122,395,127,391,134,377,130,370,120,365,115,356,111,337,105,319" />
            <area id="region-10" onclick="{!c.select}" onmouseenter="{!c.mouseEnter}"  onmouseleave="{!c.mouseLeave}" data-region="region-10" title="Region 10" shape="poly" coords="152,351,181,353,187,329,223,333,226,298,219,297,221,277,127,259,127,270,120,264,107,212,114,201,104,168,96,168,87,152,120,80,80,42,43,45,20,70,3,107,12,144,37,148,53,133,79,151,98,183,122,277,111,302,146,312,142,321,152,324,149,332,157,333" />
            <area id="region-11" onclick="{!c.select}" onmouseenter="{!c.mouseEnter}"  onmouseleave="{!c.mouseLeave}" data-region="region-11" title="Region 11" shape="poly" coords="259,279,192,272,129,260,120,265,112,241,115,237,106,214,114,203,102,168,86,152,118,82,158,91,175,74,182,56,192,38,232,12,254,1,316,1,311,30,302,61,310,73,325,77,352,106,379,128,375,151,378,172,347,158,325,154,311,166,307,177,297,170,290,156,279,163,262,188,270,209,284,220,257,251" />
            <area id="region-12" onclick="{!c.select}" onmouseenter="{!c.mouseEnter}"  onmouseleave="{!c.mouseLeave}" data-region="region-12" title="Region 12" shape="poly" coords="322,327,340,312,362,299,343,290,334,273,333,258,319,247,316,235,312,230,305,233,288,219,259,250,258,276,278,285,288,283,300,281,308,292,317,299,328,297,333,306" />
            <area id="region-13" onclick="{!c.select}" onmouseenter="{!c.mouseEnter}"  onmouseleave="{!c.mouseLeave}" data-region="region-13" title="Region 13" shape="poly" coords="344,294,361,295,374,297,384,283,390,277,396,289,408,300,426,286,427,272,410,277,401,272,405,262,393,258,413,257,416,247,431,235,430,257,457,257,454,244,441,240,440,227,425,213,399,200,382,176,374,193,367,196,361,183,358,176,329,173,328,197,339,210,328,230,331,253,336,283" />
        </map>
    </div> 
</aura:component>

Controller:

 ({
    doInit : function(component, event, helper) {
        var displayImage = $A.get('$Resource.MapImages') + '/Main.png';
        component.set("v.displayImage", displayImage)
        component.set("v.staticImage" , displayImage);
    },

    mapResizer : function(component, event, helper) {
        console.log("$('map')");
        $('map').imageMapResize();
    },

    select : function(component, event, helper) {
        var staticImage = $A.get('$Resource.MapImages') + '/' + event.currentTarget.id + '.png';
        component.set("v.displayImage" , staticImage);
        component.set("v.staticImage" , staticImage); 
        var cmpEvent = component.getEvent("regionChangedEvent");
        var regionName = event.currentTarget.id;        
        cmpEvent.setParams({
            "regionName" : regionName});
        cmpEvent.fire();
    },

    mouseEnter : function(component, event, helper) {
        var displayImage = $A.get('$Resource.MapImages') + '/' + event.currentTarget.id + '.png';
        component.set("v.displayImage" , displayImage);
    },

    mouseLeave : function(component, event, helper) {
        var staticImage = component.get("v.staticImage")
        component.set("v.displayImage" , staticImage);

    }
})

Best Answer

One way to do so is when resources are loaded then automatically selecting all images one by one.

afterResourceLoaded : function(component, event, helper) {
        for(var i=1;i<14;i++){
           var staticImage = $A.get('$Resource.MapImages') + '/region-'i + '.png';
           component.set("v.displayImage" , staticImage);
           component.set("v.staticImage" , staticImage); 
        }  
        var displayImage = $A.get('$Resource.MapImages') + '/Main.png';
        component.set("v.displayImage", displayImage)
        component.set("v.staticImage" , displayImage);     
    },

if Image are even then are not caching then you can add a delay

afterResourceLoaded : function(component, event, helper) {
        for(var i=1;i<14;i++){
          setTimeout(function() { 
                var staticImage = $A.get('$Resource.MapImages') + '/region-'i + '.png';
                component.set("v.displayImage" , staticImage);
                component.set("v.staticImage" , staticImage); 
           },i*100);
        }  
        setTimeout(function() {
             var displayImage = $A.get('$Resource.MapImages') + '/Main.png';
             component.set("v.displayImage", displayImage)
             component.set("v.staticImage" , displayImage);
        },14*100);  
    }
Related Topic