added positioning of images

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

View File

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

View File

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

View File

@ -1,5 +1,6 @@
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
require "compass/sprites"
require 'digest/md5'
describe Compass::Sprites do
@ -19,6 +20,12 @@ describe Compass::Sprites do
def image_size(file)
IO.read(File.join(@images_tmp_path, file))[0x10..0x18].unpack('NN')
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)
scss = %Q(@import "compass"; #{scss})
@ -53,6 +60,7 @@ describe Compass::Sprites do
}
CSS
image_size('squares.png').should == [20, 30]
image_md5('squares.png').should == 'ac68084abb8f43794a75c5fb28bd62fe'
end
it "should generate sprite classes with dimensions" do
@ -125,7 +133,7 @@ describe Compass::Sprites do
CSS
image_size('squares.png').should == [20, 30]
end
it "should calculate the spacing between images but not before first image" do
css = render <<-SCSS
$squares-10x10-spacing: 33px;
@ -147,7 +155,7 @@ describe Compass::Sprites do
CSS
image_size('squares.png').should == [20, 63]
end
it "should calculate the spacing between images" do
css = render <<-SCSS
$squares-20x20-spacing: 33px;
@ -169,7 +177,7 @@ describe Compass::Sprites do
CSS
image_size('squares.png').should == [20, 63]
end
it "should calculate the maximum spacing between images" do
css = render <<-SCSS
$squares-10x10-spacing: 44px;
@ -192,7 +200,7 @@ describe Compass::Sprites do
CSS
image_size('squares.png').should == [20, 74]
end
it "should calculate the maximum spacing between images in reversed order" do
css = render <<-SCSS
$squares-10x10-spacing: 33px;
@ -215,7 +223,7 @@ describe Compass::Sprites do
CSS
image_size('squares.png').should == [20, 74]
end
it "should calculate the default spacing between images" do
css = render <<-SCSS
$squares-spacing: 22px;
@ -238,4 +246,80 @@ describe Compass::Sprites do
image_size('squares.png').should == [20, 52]
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