1

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);

    }
})
1

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);  
    }
1
  • Thank you Manjot. I was really excited when i saw your answer. I thought this should definitely work. Unfortunately it doesn't. I think the browser or the lightning framework is intelligent enough to know that those images are not being rendered on screen and hence does not cache them.
    – Rohitha
    Aug 29 '17 at 0:31
0

I did some digging and i was finally able to find a way to force the browser to cache all the images. I ended up writing a javascript function to preload all the images.

Controller:

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

Helper:

preloadImages: function (component) {
    for(var i=1; i<14; i++) {             
        var img = new Image();
        img.onload = function() {
            console.log("Image loaded");
        }
        img.src = $A.get('$Resource.MapImages') + '/Region'+ i + '.png';
    }
} 

This forces the browser to cache all the images on startup.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.