added positioning of images

This commit is contained in:
Nico Hagenburger 2010-10-17 19:38:32 +02:00 committed by Chris Eppstein
parent 573d1a1b03
commit 8b566765b3
3 changed files with 130 additions and 21 deletions

View File

@ -1,11 +1,12 @@
require 'chunky_png' require 'chunky_png'
module Compass::SassExtensions::Functions::Sprites module Compass::SassExtensions::Functions::Sprites
SASS_NULL = Sass::Script::Number::new(0)
def sprite_image(uri) def sprite_image(uri)
uri = uri.value uri = uri.value
path, name = Compass::Sprites.path_and_name(uri) path, name = Compass::Sprites.path_and_name(uri)
last_spacing = 0 last_spacing = 0
default_spacing = number_from_var("#{name}-spacing")
width = 0 width = 0
height = 0 height = 0
images = Compass::Sprites.sprites(name) images = Compass::Sprites.sprites(name)
@ -14,7 +15,7 @@ module Compass::SassExtensions::Functions::Sprites
images.each do |image| images.each do |image|
current_spacing = number_from_var("#{name}-#{image[:name]}-spacing") current_spacing = number_from_var("#{name}-#{image[:name]}-spacing")
if height > 0 if height > 0
height += [current_spacing, last_spacing, default_spacing].max height += [current_spacing, last_spacing].max
end end
image[:y] = height image[:y] = height
height += image[:height] height += image[:height]
@ -26,21 +27,32 @@ module Compass::SassExtensions::Functions::Sprites
output_png = ChunkyPNG::Image.new(width, height, ChunkyPNG::Color::TRANSPARENT) output_png = ChunkyPNG::Image.new(width, height, ChunkyPNG::Color::TRANSPARENT)
images.each do |image| images.each do |image|
input_png = ChunkyPNG::Image.from_file(image[:file]) input_png = ChunkyPNG::Image.from_file(image[:file])
x = 0 position = environment.var("#{name}-#{image[:name]}-position")
y = image[:y] if position.unit_str == "%"
output_png.replace input_png, x, y image[:x] = (width - image[:width]) * (position.value / 100)
else
image[:x] = position.value
end
output_png.replace input_png, image[:x], image[:y]
end end
output_png.save File.join(File.join(Compass.configuration.images_path, "#{path}.png")) output_png.save File.join(File.join(Compass.configuration.images_path, "#{path}.png"))
image_url(Sass::Script::String.new("#{path}.png")) image_url(Sass::Script::String.new("#{path}.png"))
end end
def sprite_position(file) def sprite_position(file, x_shift = SASS_NULL, y_shift = SASS_NULL)
name = File.dirname(file.value) name = File.dirname(file.value)
sprite = File.basename(file.value, '.png') image_name = File.basename(file.value, '.png')
y = Compass::Sprites.sprites(name).detect{ |sprite_info| sprite_info[:name] == sprite }[:y] image = Compass::Sprites.sprites(name).detect{ |image| image[:name] == image_name }
y = "-#{y}px" unless y == 0 if x_shift.unit_str == "%"
Sass::Script::String.new("0 #{y}") x = x_shift.to_s
else
x = x_shift.value - image[:x]
x = "#{x}px" unless x == 0
end
y = y_shift.value - image[:y]
y = "#{y}px" unless y == 0
Sass::Script::String.new("#{x} #{y}")
end end
private private

View File

@ -42,6 +42,15 @@ module Compass
contents = <<-SCSS contents = <<-SCSS
$#{name}-sprite-base-class: ".#{name}-sprite" !default; $#{name}-sprite-base-class: ".#{name}-sprite" !default;
$#{name}-sprite-dimensions: false !default; $#{name}-sprite-dimensions: false !default;
$#{name}-position: 0% !default;
$#{name}-spacing: 0 !default;
#{images.map do |sprite|
<<-SCSS
$#{name}-#{sprite[:name]}-position: $#{name}-position !default;
$#{name}-#{sprite[:name]}-spacing: $#{name}-spacing !default;
SCSS
end.join}
\#{$#{name}-sprite-base-class} { \#{$#{name}-sprite-base-class} {
background: sprite-image("#{uri}") no-repeat; background: sprite-image("#{uri}") no-repeat;
@ -52,13 +61,13 @@ module Compass
width: image-width("#{name}/\#{$sprite}.png"); width: image-width("#{name}/\#{$sprite}.png");
} }
@mixin #{name}-sprite-position($sprite) { @mixin #{name}-sprite-position($sprite, $x: 0, $y: 0) {
background-position: sprite-position("#{path}/\#{$sprite}.png"); background-position: sprite-position("#{path}/\#{$sprite}.png", $x, $y);
} }
@mixin #{name}-sprite($sprite, $dimensions: $#{name}-sprite-dimensions) { @mixin #{name}-sprite($sprite, $dimensions: $#{name}-sprite-dimensions, $x: 0, $y: 0) {
@extend \#{$#{name}-sprite-base-class}; @extend \#{$#{name}-sprite-base-class};
@include #{name}-sprite-position($sprite); @include #{name}-sprite-position($sprite, $x, $y);
@if $dimensions { @if $dimensions {
@include #{name}-sprite-dimensions($sprite); @include #{name}-sprite-dimensions($sprite);
} }
@ -66,8 +75,12 @@ module Compass
@mixin all-#{name}-sprites { @mixin all-#{name}-sprites {
#{images.map do |sprite| #{images.map do |sprite|
%Q(.#{name}-#{sprite[:name]} { @include #{name}-sprite("#{sprite[:name]}"); }) <<-SCSS
end.join} .#{name}-#{sprite[:name]} {
@include #{name}-sprite("#{sprite[:name]}");
}
SCSS
end.join}
} }
SCSS SCSS
options.merge! :filename => name, :syntax => :scss, :importer => self options.merge! :filename => name, :syntax => :scss, :importer => self

View File

@ -1,5 +1,6 @@
require File.expand_path(File.dirname(__FILE__) + '/spec_helper') require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
require "compass/sprites" require "compass/sprites"
require 'digest/md5'
describe Compass::Sprites do describe Compass::Sprites do
@ -19,6 +20,12 @@ describe Compass::Sprites do
def image_size(file) def image_size(file)
IO.read(File.join(@images_tmp_path, file))[0x10..0x18].unpack('NN') IO.read(File.join(@images_tmp_path, file))[0x10..0x18].unpack('NN')
end end
def image_md5(file)
md5 = Digest::MD5.new
md5.update IO.read(File.join(@images_tmp_path, file))
md5.hexdigest
end
def render(scss) def render(scss)
scss = %Q(@import "compass"; #{scss}) scss = %Q(@import "compass"; #{scss})
@ -53,6 +60,7 @@ describe Compass::Sprites do
} }
CSS CSS
image_size('squares.png').should == [20, 30] image_size('squares.png').should == [20, 30]
image_md5('squares.png').should == 'ac68084abb8f43794a75c5fb28bd62fe'
end end
it "should generate sprite classes with dimensions" do it "should generate sprite classes with dimensions" do
@ -125,7 +133,7 @@ describe Compass::Sprites do
CSS CSS
image_size('squares.png').should == [20, 30] image_size('squares.png').should == [20, 30]
end end
it "should calculate the spacing between images but not before first image" do it "should calculate the spacing between images but not before first image" do
css = render <<-SCSS css = render <<-SCSS
$squares-10x10-spacing: 33px; $squares-10x10-spacing: 33px;
@ -147,7 +155,7 @@ describe Compass::Sprites do
CSS CSS
image_size('squares.png').should == [20, 63] image_size('squares.png').should == [20, 63]
end end
it "should calculate the spacing between images" do it "should calculate the spacing between images" do
css = render <<-SCSS css = render <<-SCSS
$squares-20x20-spacing: 33px; $squares-20x20-spacing: 33px;
@ -169,7 +177,7 @@ describe Compass::Sprites do
CSS CSS
image_size('squares.png').should == [20, 63] image_size('squares.png').should == [20, 63]
end end
it "should calculate the maximum spacing between images" do it "should calculate the maximum spacing between images" do
css = render <<-SCSS css = render <<-SCSS
$squares-10x10-spacing: 44px; $squares-10x10-spacing: 44px;
@ -192,7 +200,7 @@ describe Compass::Sprites do
CSS CSS
image_size('squares.png').should == [20, 74] image_size('squares.png').should == [20, 74]
end end
it "should calculate the maximum spacing between images in reversed order" do it "should calculate the maximum spacing between images in reversed order" do
css = render <<-SCSS css = render <<-SCSS
$squares-10x10-spacing: 33px; $squares-10x10-spacing: 33px;
@ -215,7 +223,7 @@ describe Compass::Sprites do
CSS CSS
image_size('squares.png').should == [20, 74] image_size('squares.png').should == [20, 74]
end end
it "should calculate the default spacing between images" do it "should calculate the default spacing between images" do
css = render <<-SCSS css = render <<-SCSS
$squares-spacing: 22px; $squares-spacing: 22px;
@ -238,4 +246,80 @@ describe Compass::Sprites do
image_size('squares.png').should == [20, 52] image_size('squares.png').should == [20, 52]
end end
it "should use position adjustments in functions" do
css = render <<-SCSS
$squares-position: 100%;
@import "squares/*.png";
.adjusted-percentage {
background-position: sprite-position("squares/10x10.png", 100%);
}
.adjusted-px-1 {
background-position: sprite-position("squares/10x10.png", 4px);
}
.adjusted-px-2 {
background-position: sprite-position("squares/20x20.png", -3px, 2px);
}
SCSS
css.should == <<-CSS
.squares-sprite {
background: url('/squares.png') no-repeat;
}
.adjusted-percentage {
background-position: 100% 0;
}
.adjusted-px-1 {
background-position: -6px 0;
}
.adjusted-px-2 {
background-position: -3px -8px;
}
CSS
image_size('squares.png').should == [20, 30]
image_md5('squares.png').should == 'e274a620ff44c14774fa470d0a9020a1'
end
it "should use position adjustments in mixins" do
css = render <<-SCSS
$squares-position: 100%;
@import "squares/*.png";
.adjusted-percentage {
@include squares-sprite("10x10", $x: 100%);
}
.adjusted-px-1 {
@include squares-sprite("10x10", $x: 4px);
}
.adjusted-px-2 {
@include squares-sprite("20x20", $x: -3px, $y: 2px);
}
SCSS
css.should == <<-CSS
.squares-sprite, .adjusted-percentage, .adjusted-px-1, .adjusted-px-2 {
background: url('/squares.png') no-repeat;
}
.adjusted-percentage {
background-position: 100% 0;
}
.adjusted-px-1 {
background-position: -6px 0;
}
.adjusted-px-2 {
background-position: -3px -8px;
}
CSS
image_size('squares.png').should == [20, 30]
image_md5('squares.png').should == 'e274a620ff44c14774fa470d0a9020a1'
end
end end