diff --git a/lib/OpenLayers/Map.js b/lib/OpenLayers/Map.js index c8963747ef..07c15496ed 100644 --- a/lib/OpenLayers/Map.js +++ b/lib/OpenLayers/Map.js @@ -2660,41 +2660,61 @@ OpenLayers.Map = OpenLayers.Class({ * the map's * scale - {Number} scale. Defaults to 1 if not provided. */ - applyTransform: function(dx, dy, scale) { - var origin = this.layerContainerOriginPx; - dx = dx || origin.x; - dy = dy || origin.y; - scale = scale || 1; + applyTransform: function(x, y, scale) { + scale = scale || 1; + var origin = this.layerContainerOriginPx, + needTransform = scale !== 1; + x = x || origin.x; + y = y || origin.y; - var style = this.layerContainerDiv.style, - transform = this.applyTransform.transform, - template = this.applyTransform.template; + var style = this.layerContainerDiv.style, + transform = this.applyTransform.transform, + template = this.applyTransform.template; - if (transform === undefined) { - transform = OpenLayers.Util.vendorPrefix.style('transform'); - this.applyTransform.transform = transform; - } - - if (transform) { - if (!template) { - // try translate3d - template = ['translate3d(', ',0) ', 'scale3d(', ',1)']; - style[transform] = [template[0], '0,0', template[1]].join(''); - // if translate3d does not stick, use translate and scale - if (!~style[transform].indexOf(template[0])) { - template = ['translate(', ') ', 'scale(', ')']; - } - this.applyTransform.template = template; - } - style[transform] = [ - template[0], dx, 'px,', dy, 'px', template[1], - template[2], scale, ',', scale, template[3] - ].join(''); - } else { - style.left = dx + 'px'; - style.top = dy + 'px'; - } - }, + if (transform === undefined) { + transform = OpenLayers.Util.vendorPrefix.style('transform'); + this.applyTransform.transform = transform; + if (transform) { + // Try translate3d, but only if the viewPortDiv has a transform + // defined in a stylesheet + var computedStyle = OpenLayers.Element.getStyle(this.viewPortDiv, OpenLayers.Util.vendorPrefix.css('transform')); + if (!computedStyle || computedStyle !== 'none') { + template = ['translate3d(', ',0) ', 'scale3d(', ',1)']; + style[transform] = [template[0], '0,0', template[1]].join(''); + } + // If no transform is defined in the stylesheet or translate3d + // does not stick, use translate and scale + if (!template || !~style[transform].indexOf(template[0])) { + template = ['translate(', ') ', 'scale(', ')']; + } + this.applyTransform.template = template; + } + } + + // If we do 3d transforms, we always want to use them. If we do 2d + // transforms, we only use them when we need to. + if (transform !== null && (template[0] === 'translate3d(' || needTransform === true)) { + // Our 2d transforms are combined with style.left and style.top, so + // adjust x and y values and set the origin as left and top + if (needTransform === true && template[0] === 'translate(') { + x -= origin.x; + y -= origin.y; + style.left = origin.x + 'px'; + style.top = origin.y + 'px'; + } + style[transform] = [ + template[0], x, 'px,', y, 'px', template[1], + template[2], scale, ',', scale, template[3] + ].join(''); + } else { + style.left = x + 'px'; + style.top = y + 'px'; + // We previously might have had needTransform, so remove transform + if (transform !== null) { + style[transform] = ''; + } + } + }, CLASS_NAME: "OpenLayers.Map" }); diff --git a/tests/Map.html b/tests/Map.html index e57020b065..fb05de0ffd 100644 --- a/tests/Map.html +++ b/tests/Map.html @@ -2065,33 +2065,45 @@ } function test_applyTransform(t) { - t.plan(4); + t.plan(10); + var origStylePrefix = OpenLayers.Util.vendorPrefix.style; + OpenLayers.Util.vendorPrefix.style = function(key) { return 'transform'; }; var map = new OpenLayers.Map('map'); map.layerContainerDiv = {style: {}}; delete map.applyTransform.transform; delete map.applyTransform.template; - var origStylePrefix = OpenLayers.Util.vendorPrefix.style; - OpenLayers.Util.vendorPrefix.style = function(key) { return 'transform'; }; + var origGetStyle = OpenLayers.Element.getStyle; + OpenLayers.Element.getStyle = function() { return 'foo'; } map.applyTransform(1, 2, 3); - OpenLayers.Util.vendorPrefix.style = origStylePrefix; + OpenLayers.Element.getStyle = origGetStyle; t.eq(map.layerContainerDiv.style.transform, 'translate3d(1px,2px,0) scale3d(3,3,1)', '3d transform and scale used when available'); + delete map.applyTransform.transform; delete map.applyTransform.template; var origIndexOf = String.prototype.indexOf; String.prototype.indexOf = function() { return -1; }; + map.layerContainerOriginPx = {x: -3, y: 2}; map.applyTransform(1, 2, 3); String.prototype.indexOf = origIndexOf; - t.eq(map.layerContainerDiv.style.transform, 'translate(1px,2px) scale(3,3)', '2d translate and scale correct'); + t.eq(map.layerContainerDiv.style.transform, 'translate(4px,0px) scale(3,3)', '2d translate and scale correct'); + t.eq(map.layerContainerDiv.style.left, '-3px', 'container origin x set as style.left'); + t.eq(map.layerContainerDiv.style.top, '2px', 'container origin y set as style.top'); + map.applyTransform(1, 2); + t.ok(!map.layerContainerDiv.style.transform, 'no transform set when no transform needed'); + t.eq(map.layerContainerDiv.style.left, '1px', 'style.left correct when no transform needed'); + t.eq(map.layerContainerDiv.style.top, '2px', 'style.top correct when no transform needed'); map.applyTransform.transform = null; map.applyTransform(4, 5, 6); t.eq(map.layerContainerDiv.style.left, '4px', 'style.left set when transform not available') t.eq(map.layerContainerDiv.style.top, '5px', 'style.top set when transform not available') + t.ok(!map.layerContainerDiv.style.transform, 'no transform set, because not supported'); map.destroy(); delete map.applyTransform.transform; delete map.applyTransform.template; + OpenLayers.Util.vendorPrefix.style = origStylePrefix; } function test_options(t) {