diff --git a/lib/spriteBackgroundImages.js b/lib/spriteBackgroundImages.js index 190dd38..3813601 100644 --- a/lib/spriteBackgroundImages.js +++ b/lib/spriteBackgroundImages.js @@ -110,6 +110,8 @@ module.exports = function () { } var spriteGroups = {}; + + // Find sprite annotated images and create a data structure with their information assetGraph.findRelations({type: 'CssImage', to: {isImage: true}, href: /\?(?:|[^#]*&)sprite(?:[=&#]|$)/}).forEach(function (relation) { var relationSpriteInfo = getRelationSpriteInfoFromIncomingRelation(relation), spriteGroup = (spriteGroups[relationSpriteInfo.groupName] = spriteGroups[relationSpriteInfo.groupName] || { @@ -127,6 +129,7 @@ module.exports = function () { } }); + // Extract sprite grouping information va -sprite- prefixed properties in stylesheets assetGraph.findAssets({type: 'Css'}).forEach(function (cssAsset) { cssAsset.eachRuleInParseTree(function (cssRule) { if (cssRule.type !== 1) { // cssom.CSSRule.STYLE_RULE @@ -190,7 +193,8 @@ module.exports = function () { var callback = this, spriteGroup = spriteGroups[spriteGroupName], imageInfos = _.values(spriteGroup.imageInfosById), - spriteInfo = spriteGroup.placeHolders && spriteGroup.placeHolders[0] || {}; + spriteInfo = spriteGroup.placeHolders && spriteGroup.placeHolders[0] || {}, + packingData; seq(imageInfos) .parMap(function (imageInfo) { @@ -210,9 +214,12 @@ module.exports = function () { horizontal: 'horizontal', vertical: 'vertical' }[spriteInfo.packer] || 'tryAll'; - var packingData = packers[packerName].pack(imageInfos), - canvas = new Canvas(packingData.width, packingData.height), + + packingData = packers[packerName].pack(imageInfos); + + var canvas = new Canvas(packingData.width, packingData.height), ctx = canvas.getContext('2d'); + imageInfos = packingData.imageInfos; if ('backgroundColor' in spriteInfo) { ctx.fillStyle = spriteInfo.backgroundColor; @@ -281,6 +288,11 @@ module.exports = function () { ['selector-for-group', 'packer', 'image-format', 'background-color', 'important'].forEach(function (propertyName) { spriteInfo.cssRule.style.removeProperty('-sprite-' + propertyName); }); + + // If background-size is set, we should update it, The correct size is now the sprites size + if (spriteInfo.cssRule.style.getPropertyValue('background-size')) { + spriteInfo.cssRule.style.setProperty('background-size', packingData.width + 'px ' + packingData.height + 'px'); + } }); } imageInfos.forEach(function (imageInfo) { @@ -351,6 +363,21 @@ module.exports = function () { ['group', 'padding', 'no-group-selector', 'important'].forEach(function (propertyName) { style.removeProperty('-sprite-' + propertyName); }); + + // Background-sizes change when spriting, upadte appropriately + if (imageInfo.asset.devicePixelRatio === 1) { + // Device pixel ratio is default. Remove property and let the defaults rule + incomingRelation.cssRule.style.removeProperty('background-size'); + } else { + // Device pixel ratio is non-default, Set it explicitly with the ratio applied + var dpr = incomingRelation.to.devicePixelRatio; + + // TODO: Figure out if rounding might become a problem + var width = packingData.width / dpr; + var height = packingData.height / dpr; + incomingRelation.cssRule.style.setProperty('background-size', width + 'px ' + height + 'px'); + } + if (relationSpriteInfo.noGroup || !spriteGroup.placeHolders) { // The user specified that this selector needs its own background-image/background // property pointing at the sprite rather than relying on the Html elements also being diff --git a/package.json b/package.json index 0524b4c..23fec01 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "canvas": "=1.1.2" }, "devDependencies": { - "assetgraph": "1.14.4", + "assetgraph": "1.15.0", "coveralls": "^2.11.1", "istanbul": "^0.3.0", "jshint": "=2.5.1", diff --git a/test/spriteBackgroundImages.js b/test/spriteBackgroundImages.js index a590d74..e38c1ba 100644 --- a/test/spriteBackgroundImages.js +++ b/test/spriteBackgroundImages.js @@ -257,4 +257,43 @@ describe('spriteBackgroundImages', function () { }) .run(done); }); + + it('should get the background-position right when spriting a @2x image', function (done) { + new AssetGraph({root: __dirname + '/../testdata/spriteBackgroundImages/retina/'}) + .loadAssets('index.html') + .populate() + .queue(function (assetGraph) { + expect(assetGraph, 'to contain assets', 'Css', 1); + expect(assetGraph, 'to contain assets', 'Png', 2); + expect(assetGraph, 'to contain assets', { type: 'Png', devicePixelRatio: 1 }, 1); + expect(assetGraph, 'to contain assets', { type: 'Png', devicePixelRatio: 2 }, 1); + + assetGraph.findRelations({ type: 'CssImage', cssRule: { selectorText: '.regular' } }).forEach(function (relation) { + expect(relation.to.devicePixelRatio, 'to be', 1); + expect(relation.cssRule.style, 'not to have property', 'background-size'); + }); + + assetGraph.findRelations({ type: 'CssImage', cssRule: { selectorText: '.retina' } }).forEach(function (relation) { + expect(relation.to.devicePixelRatio, 'to be', 2); + expect(relation.cssRule.style, 'not to have property', 'background-size'); + }); + }) + .queue(spriteBackgroundImages()) + .queue(function (assetGraph) { + expect(assetGraph, 'to contain asset', 'Png', 1); + expect(assetGraph, 'to contain relations', 'CssImage', 2); + expect(assetGraph, 'to contain relations', { type: 'CssImage', cssRule: { selectorText: '.regular' } }, 1); + expect(assetGraph, 'to contain relations', { type: 'CssImage', cssRule: { selectorText: '.retina' } }, 1); + + assetGraph.findRelations({ type: 'CssImage', cssRule: { selectorText: '.regular' } }).forEach(function (relation) { + expect(relation.cssRule.style, 'not to have property', 'background-size'); + }); + + assetGraph.findRelations({ type: 'CssImage', cssRule: { selectorText: '.retina' } }).forEach(function (relation) { + expect(relation.cssRule.style, 'to have property', 'background-size'); + expect(relation.cssRule.style.getPropertyValue('background-size'), 'to be', '88.5px 59px'); + }); + }) + .run(done); + }); }); diff --git a/testdata/spriteBackgroundImages/retina/index.html b/testdata/spriteBackgroundImages/retina/index.html new file mode 100644 index 0000000..29a45f7 --- /dev/null +++ b/testdata/spriteBackgroundImages/retina/index.html @@ -0,0 +1,23 @@ + + + + + + + +
+
+ + \ No newline at end of file diff --git a/testdata/spriteBackgroundImages/retina/settings.png b/testdata/spriteBackgroundImages/retina/settings.png new file mode 100644 index 0000000..188a648 Binary files /dev/null and b/testdata/spriteBackgroundImages/retina/settings.png differ diff --git a/testdata/spriteBackgroundImages/retina/settings@2x.png b/testdata/spriteBackgroundImages/retina/settings@2x.png new file mode 100644 index 0000000..d6f33ea Binary files /dev/null and b/testdata/spriteBackgroundImages/retina/settings@2x.png differ