/** * @ignore * transform hack for ie * @author yiminghe@gmail.com */ KISSY.add('dom/ie/transform', function (S, Dom) { var cssHooks = Dom._cssHooks; var rMatrix = /progid:DXImageTransform.Microsoft.Matrix\(([^)]*)\)/; cssHooks.transform = { get: function (elem, computed) { var elemStyle = elem[computed ? 'currentStyle' : 'style'], matrix; if (elemStyle && rMatrix.test(elemStyle.filter)) { matrix = RegExp.$1.split(","); var dx = 0 , dy = 0; var dxs = matrix[4] && matrix[4].split("="); var dys = matrix[5] && matrix[5].split("="); if (dxs && dxs[0].toLowerCase() == 'dx') { dx = parseFloat(dxs[1]); } if (dys && dys[0].toLowerCase() == 'dy') { dy = parseFloat(dys[1]); } matrix = [ matrix[0].split("=")[1], matrix[2].split("=")[1], matrix[1].split("=")[1], matrix[3].split("=")[1], dx, dy ]; } else { return computed ? 'none' : ''; } return 'matrix(' + matrix.join(',') + ')'; }, set: function (elem, value) { var elemStyle = elem.style, currentStyle = elem.currentStyle, matrixVal, region = { width: elem.clientWidth, height: elem.clientHeight }, center = { x: region.width / 2, y: region.height / 2 }, // ie must be set inline origin = parseOrigin(elem.style['transformOrigin'], region), filter; elemStyle.zoom = 1; if (value) { value = matrix(value); var afterCenter = getCenterByOrigin(value, origin, center); afterCenter.x = afterCenter[0][0]; afterCenter.y = afterCenter[1][0]; matrixVal = [ "progid:DXImageTransform.Microsoft.Matrix(" + "M11=" + value[0][0], "M12=" + value[0][1], "M21=" + value[1][0], "M22=" + value[1][1], // no effect in this filter set // but used for get to keep status // Dom.css(t,'transform',Dom.css(t,'transform')) "Dx=" + value[0][2], "Dy=" + value[1][2], 'SizingMethod="auto expand"' ].join(',') + ')'; } else { matrixVal = ''; } filter = currentStyle && currentStyle.filter || elemStyle.filter || ""; if (!matrixVal && !S.trim(filter.replace(rMatrix, ''))) { // Setting style.filter to null, '' & ' ' still leave 'filter:' in the cssText // if 'filter:' is present at all, clearType is disabled, we want to avoid this // style.removeAttribute is IE Only, but so apparently is this code path... elemStyle.removeAttribute('filter'); if (// unset inline opacity !matrixVal || // if there is no filter style applied in a css rule, we are done currentStyle && !currentStyle.filter) { return; } } // otherwise, set new filter values // 如果不设,就不能覆盖外部样式表定义的样式,一定要设 elemStyle.filter = rMatrix.test(filter) ? filter.replace(rMatrix, matrixVal) : filter + (filter ? ', ' : '') + matrixVal; if (matrixVal) { var realCenter = { x: elem.offsetWidth / 2, y: elem.offsetHeight / 2 }; elemStyle.marginLeft = afterCenter.x - realCenter.x + 'px'; elemStyle.marginTop = afterCenter.y - realCenter.y + 'px'; } else { elemStyle.marginLeft = elemStyle.marginTop = 0; } } }; function getCenterByOrigin(m, origin, center) { var w = origin[0], h = origin[1]; return multipleMatrix([ [1, 0, w], [0, 1, h], [0, 0, 1] ], m, [ [1, 0, -w], [0, 1, -h], [0, 0, 1] ], [ [center.x], [center.y], [1] ]); } function parseOrigin(origin, region) { origin = origin || '50% 50%'; origin = origin.split(/\s+/); if (origin.length == 1) { origin[1] = origin[0]; } for (var i = 0; i < origin.length; i++) { var val = parseFloat(origin[i]); if (S.endsWith(origin[i], '%')) { origin[i] = val * region[i ? 'height' : 'width'] / 100; } else { origin[i] = val; } } return origin; } // turn transform string into standard matrix form function matrix(transform) { transform = transform.split(")"); var trim = S.trim, i = -1, l = transform.length - 1, split, prop, val, ret = cssMatrixToComputableMatrix([1, 0, 0, 1, 0, 0]), curr; // Loop through the transform properties, parse and multiply them while (++i < l) { split = transform[i].split("("); prop = trim(split[0]); val = split[1]; curr = [1, 0, 0, 1, 0, 0]; switch (prop) { case "translateX": curr[4] = parseInt(val, 10); break; case "translateY": curr[5] = parseInt(val, 10); break; case 'translate': val = val.split(","); curr[4] = parseInt(val[0], 10); curr[5] = parseInt(val[1] || 0, 10); break; case 'rotate': val = toRadian(val); curr[0] = Math.cos(val); curr[1] = Math.sin(val); curr[2] = -Math.sin(val); curr[3] = Math.cos(val); break; case 'scaleX': curr[0] = +val; break; case 'scaleY': curr[3] = +val; break; case 'scale': val = val.split(","); curr[0] = +val[0]; curr[3] = val.length > 1 ? +val[1] : +val[0]; break; case "skewX": curr[2] = Math.tan(toRadian(val)); break; case "skewY": curr[1] = Math.tan(toRadian(val)); break; case 'matrix': val = val.split(","); curr[0] = +val[0]; curr[1] = +val[1]; curr[2] = +val[2]; curr[3] = +val[3]; curr[4] = parseInt(val[4], 10); curr[5] = parseInt(val[5], 10); break; } ret = multipleMatrix(ret, cssMatrixToComputableMatrix(curr)); } return ret; } function cssMatrixToComputableMatrix(matrix) { return[ [matrix[0], matrix[2], matrix[4]], [matrix[1], matrix[3], matrix[5]], [0, 0, 1] ]; } function setMatrix(m, x, y, v) { if (!m[x]) { m[x] = []; } m[x][y] = v; } function multipleMatrix(m1, m2) { if (arguments.length > 2) { var ret = m1; for (var i = 1; i < arguments.length; i++) { ret = multipleMatrix(ret, arguments[i]); } return ret; } var m = [], r1 = m1.length, r2 = m2.length, c2 = m2[0].length; for (i = 0; i < r1; i++) { for (var k = 0; k < c2; k++) { var sum = 0; for (var j = 0; j < r2; j++) { sum += m1[i][j] * m2[j][k]; } setMatrix(m, i, k, sum); } } return m; } // converts an angle string in any unit to a radian Float function toRadian(value) { return value.indexOf("deg") > -1 ? parseInt(value, 10) * (Math.PI * 2 / 360) : parseFloat(value); } }, { requires: ['dom/base'] }); /** * @ignore * refer: * - https://github.com/louisremi/jquery.transform.js * - http://hg.mozilla.org/mozilla-central/file/7cb3e9795d04/layout/style/nsStyleAnimation.cpp#l971 */