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 tono-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 tomax-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...)
- I can't change the
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
/matrix\([^)]*\)
or something. – Sanjay Manohar