Archive for September, 2010

Non-Affine transforms in safari

screenshot of safari showing an image with a non-affine transform

With 3d transforms you can do a non-affine image warp. Here’s where I took the math from, but this is intended for WPF (.net), but later he created a silverlight 3 sample. http://www.charlespetzold.com/blog/2007/08/250638.html

So, safari’s version of webkit (even mobile safari) added 3d transforms: http://webkit.org/blog/386/3d-transforms/ (in safari 5 this became available in desktop safari, probably even on windows).

Today I got the minimal version of the non-affine transform example running. Here’s the code:

<!DOCTYPE HTML>
<html>
<head>
	<title>css 3d test</title>
	<style type="text/css">
body {
	margin: 0px;
}
#thing {
	-webkit-transform-origin: 0% 0%;
	opacity: .5;
/*	I can get rid of the manual scaling in the javascript with this additon:
	width: 1px;
	height: 1px; */
	position: absolute;
}
.point {
	width: 8px;
	height: 8px;
	background-color: pink;
	position: absolute;
	margin-left: -4px;
	margin-top: -4px;
}
	</style>
</head>
<body>
	<img src="IMG_0026.jpg" id="thing">

	<div id="p0" class="point" style="left: 954px; top: 257px; background-color: red;"> </div>
	<div id="p2" class="point" style="left: 1706px; top: 231px; background-color: green;"> </div>
	<div id="p3" class="point" style="left: 1685px; top: 693px; background-color: blue;"> </div>
	<div id="p1" class="point" style="left: 950px; top: 665px; background-color: yellow;"> </div>

<script type="text/javascript">
/*
non-affine transforms:
http://www.charlespetzold.com/blog/2007/08/250638.html

safari 3d transform introduction (css)
http://webkit.org/blog/386/3d-transforms/

some apple documentation:
http://developer.apple.com/library/safari/#documentation/InternetWeb/Conceptual/SafariVisualEffectsProgGuide/Transforms/Transforms.html

reference: http://www.w3.org/TR/css3-3d-transforms/
*/

//(function () {

// create a non-affine transform to move #thing's corners to those
// specified by p0 through p3
var p0 = document.getElementById('p0');
var p1 = document.getElementById('p1');
var p2 = document.getElementById('p2');
var p3 = document.getElementById('p3');
var thing = document.getElementById('thing');

var x0 = parseFloat(p0.style.left, 10)
var y0 = parseFloat(p0.style.top, 10)
var x1 = parseFloat(p1.style.left, 10)
var y1 = parseFloat(p1.style.top, 10)
var x2 = parseFloat(p2.style.left, 10)
var y2 = parseFloat(p2.style.top, 10)
var x3 = parseFloat(p3.style.left, 10)
var y3 = parseFloat(p3.style.top, 10)

var arrayToMatrix = function (array) {
	// this is a cheesy hack, I think a better approach would be
	//var x = new WebKitCSSMatrix(); x.m11=array[0] and so-on
	return new WebKitCSSMatrix('matrix3d(' + array.join(', ') + ')');
}

// 2048x1536
var matScaleDown = new WebKitCSSMatrix().scale(1/2048,1/1536,1);

var matAffineTransform = arrayToMatrix([x2-x0,y2-y0,0,0,
    x1-x0,y1-y0,0,0,
    0,0,1,0,
    0,0,0,1]);

var matTranslate = new WebKitCSSMatrix().translate(x0,y0,0);

var a = (matAffineTransform.m22 * x3 -
			matAffineTransform.m21 * y3 +
			matAffineTransform.m21 * y0 -
			matAffineTransform.m22 * x0) /
		(matAffineTransform.m11 * matAffineTransform.m22 -
			matAffineTransform.m12 * matAffineTransform.m21)
var b = (matAffineTransform.m11 * y3 -
			matAffineTransform.m12 * x3 +
			matAffineTransform.m12 * x0 -
			matAffineTransform.m11 * y0) /
		(matAffineTransform.m11 * matAffineTransform.m22 -
			matAffineTransform.m12 * matAffineTransform.m21)
var matNonAffineTransform = arrayToMatrix([a/(a+b-1),0,0,a/(a+b-1)-1,
    0,b/(a+b-1),0,b/(a+b-1)-1,
    0,0,1,0,
    0,0,0,1]);

// note: the matrix specified to multiply() is multiplied on the right
// so the matrices listed below are in reverse order:
var matResult = new WebKitCSSMatrix().
	multiply(matTranslate).
	multiply(matAffineTransform).
	multiply(matNonAffineTransform).
	multiply(matScaleDown);

thing.style['-webkit-transform'] = matResult;

//})();
</script>
</body>
</html>

http://en.support.wordpress.com/code/posting-source-code/

1 Comment