I just discovered that Chrome doesn't cache images which are placed inside SVGs if their cache-control
header is set to no-cache
. Firefox & IE10 seem to ignore this setting.
I've created a little test page with a static SVG:
HTML:
<div style="width: 500px; text-align: center;">
<input id="move-left-btn" type="button" value="<<">
<input id="move-right-btn" type="button" value=">>">
</div>
<div class="svgwrapper" style="width: 500px; height: 250px; background-color: lightgrey;">
<svg id="svg" version="1.1" xmlns="http://www.w3.org/2000/svg" width="500" height="250">
<g id="svggroup" class="transition-on" transform="matrix(0.2,0,0,0.2,80,35)">
<image width="1672" height="887" opacity="1" xlink:href="https://dl.dropboxusercontent.com/sh/q7htlj5h8qqfhjf/SVDuynM7R3/car.png"></image>
</g>
</svg>
</div>
Javascript:
$(document).ready(function() {
var curXPos = 80;
// Local test function which represent some server calls in my "real life" scenario
// Just updates the x-position in the transform matrix in this test case
function updateSvgText(svgText, posXDelta) {
curXPos += posXDelta;
if (curXPos < 0) {
curXPos = 160;
} else if (curXPos > 160) {
curXPos = 0;
}
return svgText.replace(/matrix\(.*\)/, 'matrix(0.2,0,0,0.2,' + curXPos + ',35)');
}
// Fetch the new SVG (in real life from server) and rerender it
function moveSvg(posXDelta) {
var svg = $('#svg'),
svgText = updateSvgText($('.svgwrapper').html(), posXDelta);
svg.empty();
svg.append($(svgText).children());
}
$('#move-left-btn').click($.proxy(moveSvg, this, -20));
$('#move-right-btn').click($.proxy(moveSvg, this, 20));
});
Working example with cache-control
header of source image set to no-cache
(flickers in chrome after every press on the "move" buttons):
http://jsfiddle.net/zF6NF/4/
Same example with different source image with cache-control
header set to max-age=315360000,public
(no flickering):
http://jsfiddle.net/zF6NF/5/
In Chrome you can see the reloading of the images on each button click in the first example ("flickering" of the image & visible in the network tab of the dev tools) whereas Firefox rerenders the SVG in both examples smoothly without any reloading.
Some additional information:
This is just an example. In my "real-life-scenario" I receive a new SVG from the server (instead of the updateSvgText
method call) which means that I can't just perform partial updates of the SVG by changing the value of the transform matrix attribute but have to rerender the whole SVG every time (at least by now...).
I can't control where the images come from which means 2 things:
- I can't change the
cache-control
header
- I can't create Base64 encoded data-uris, save them locally and just replace the images inside the SVG with those data-uris before rendering (can't create Base64 encoded data-uri because of "Same resource origin" policies...)
Is there any way to either...
- Overwrite/overrule the
cache-control
header locally even if the image is from an uncontrolled remote location?
- Create the Base64 encoded data-uri from an Image that is loaded from a different domain I don't have any control over client sided?
- Somehow tell Chrome to always cache images inside my SVGs?
Needless to say that other solutions are also very welcome!
Thanks