I have a simple .swf which flashes back and forth between two colours every few frames. The swf is embedded using SwfObject, and sits inside a wrapper div which is positioned on the screen using a cross-browser transform, like this:
// HTML:
<div id="wrapper">
<div id="swf" /> // Replaced with swf by SwfObject
</div>
// CSS:
#wrapper
{
width: 210pt;
height: 120pt;
-moz-transform: matrix(1,0,0,1,36,36);
-ms-transform: matrix(1,0,0,1,36,36);
-webkit-transform: matrix(1,0,0,1,36,36);
transform: matrix(1,0,0,1,36,36);
}
So far, so good. This displays fine in IE9, Chrome 21, and Firefox 15.
I then create another DIV called transformer which sits over the top of this, and use jQuery-ui draggable() to make it interactive. When I drag the transformer div, I trap the drag event, figure out the delta_x and delta_y, and add these to the existing transform using the jquery css() function – so if I drag the transformer 10px to the right, I update the tx property of the transforms by +10 to move the wrapper and its swf content.
Here’s a simplified edit of the transform code:
var dx = currentBounds.x - lastBounds.x; // delta x
var dy = currentBounds.y - lastBounds.y; // delta y
for (var i = 0; i < selectedItems.length; i++) {
var selectedItem = selectedItems[i];
var matrix = parseMatrix(selectedItem.css("transform")); // utility to read a matrix into an object
matrix.tx += dx;
matrix.ty += dy;
var newMatrix = unparseMatrix(matrix); // reverse utility
selectedItem.css("transform", newMatrix);
selectedItem.css("-moz-transform", newMatrix);
selectedItem.css("-ms-transform", newMatrix);
selectedItem.css("-webkit-transform", newMatrix);
}
Again, this works fine, apart from one oddity: whenever I drag the swf outside of its original bounds in Firefox, the stage stops being repainted, and the color sticks on whatever value it currently has. By tracing inside the swf I can see the function is still being called, and the shape is still being redrawn – it’s just that in the browser, the whole object is not being repainted. (This is only in Firefox – IE and Chrome work fine) If, however, I modify my code so that instead of moving the wrapper with a transform, I simply update the top and left properties, everything works as expected, and the stage keeps updating.
Does anyone know why this happens? My best guess is that -moz-transform takes some kind of a raster impression of an object, and then operates on that rather than the original, but I can’t understand why that only happens when you move beyond the original object’s boundaries? One more oddity is that if I right-click the transformed swf, the context menu appears as you would expect, but in Firefox it is in the original position of the swf, suggesting the transform has perhaps hidden the original and created a copy:
Any light that anyone can shed would be most welcome. Although the workaround (using top / left instead of a transform) is quite straightforward, I’d like to stick with transforms if possible, as this will interact more cleanly with other parts of my application. Also I want to be able to apply more complex transforms: will Firefox (or other browsers) rasterize a swf that is rotated?
I’ll answer this myself, just to tidy up: yes, it appears to. Experimentation shows that a rotated swf stops updating the stage once it is transformed outside its original bounds. Altering the x/y coordinates of the swf works as expected.