sprite-factory 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README.md +207 -0
- data/Rakefile +67 -0
- data/bin/sf +46 -0
- data/lib/sprite_factory.rb +51 -0
- data/lib/sprite_factory/layout.rb +89 -0
- data/lib/sprite_factory/library/chunky_png.rb +31 -0
- data/lib/sprite_factory/library/rmagick.rb +32 -0
- data/lib/sprite_factory/runner.rb +204 -0
- data/lib/sprite_factory/style.rb +58 -0
- data/sprite_factory.gemspec +24 -0
- data/test/images/custom/custom.css +4 -0
- data/test/images/custom/running.png +0 -0
- data/test/images/custom/stopped.png +0 -0
- data/test/images/empty/readme.txt +1 -0
- data/test/images/formats/alice.gif +0 -0
- data/test/images/formats/monkey.gif +0 -0
- data/test/images/formats/spies.jpg +0 -0
- data/test/images/formats/thief.png +0 -0
- data/test/images/irregular/irregular1.png +0 -0
- data/test/images/irregular/irregular2.png +0 -0
- data/test/images/irregular/irregular3.png +0 -0
- data/test/images/irregular/irregular4.png +0 -0
- data/test/images/irregular/irregular5.png +0 -0
- data/test/images/irregular/readme.txt +2 -0
- data/test/images/reference/custom.css +22 -0
- data/test/images/reference/custom.png +0 -0
- data/test/images/reference/formats.css +22 -0
- data/test/images/reference/formats.png +0 -0
- data/test/images/reference/index.html +135 -0
- data/test/images/reference/irregular.css +24 -0
- data/test/images/reference/irregular.fixed.css +24 -0
- data/test/images/reference/irregular.fixed.png +0 -0
- data/test/images/reference/irregular.horizontal.css +24 -0
- data/test/images/reference/irregular.horizontal.png +0 -0
- data/test/images/reference/irregular.padded.css +24 -0
- data/test/images/reference/irregular.padded.png +0 -0
- data/test/images/reference/irregular.png +0 -0
- data/test/images/reference/irregular.sassy.css +38 -0
- data/test/images/reference/irregular.sassy.png +0 -0
- data/test/images/reference/irregular.sassy.sass +40 -0
- data/test/images/reference/irregular.vertical.css +24 -0
- data/test/images/reference/irregular.vertical.png +0 -0
- data/test/images/reference/regular.css +24 -0
- data/test/images/reference/regular.custom.css +24 -0
- data/test/images/reference/regular.custom.png +0 -0
- data/test/images/reference/regular.fixed.css +24 -0
- data/test/images/reference/regular.fixed.png +0 -0
- data/test/images/reference/regular.horizontal.css +24 -0
- data/test/images/reference/regular.horizontal.png +0 -0
- data/test/images/reference/regular.padded.css +24 -0
- data/test/images/reference/regular.padded.png +0 -0
- data/test/images/reference/regular.png +0 -0
- data/test/images/reference/regular.sassy.css +38 -0
- data/test/images/reference/regular.sassy.png +0 -0
- data/test/images/reference/regular.sassy.sass +40 -0
- data/test/images/reference/regular.vertical.css +24 -0
- data/test/images/reference/regular.vertical.png +0 -0
- data/test/images/reference/s.gif +0 -0
- data/test/images/regular/regular1.png +0 -0
- data/test/images/regular/regular2.png +0 -0
- data/test/images/regular/regular3.png +0 -0
- data/test/images/regular/regular4.png +0 -0
- data/test/images/regular/regular5.png +0 -0
- data/test/integration_test.rb +100 -0
- data/test/layout_test.rb +228 -0
- data/test/library_test.rb +57 -0
- data/test/runner_test.rb +156 -0
- data/test/style_test.rb +64 -0
- data/test/test_case.rb +127 -0
- metadata +159 -0
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'chunky_png'
|
2
|
+
|
3
|
+
module SpriteFactory
|
4
|
+
module Library
|
5
|
+
module ChunkyPng
|
6
|
+
|
7
|
+
VALID_EXTENSIONS = :png
|
8
|
+
|
9
|
+
def self.load(files)
|
10
|
+
files.map do |filename|
|
11
|
+
image = ChunkyPNG::Image.from_file(filename)
|
12
|
+
{
|
13
|
+
:filename => filename,
|
14
|
+
:image => image,
|
15
|
+
:width => image.width,
|
16
|
+
:height => image.height
|
17
|
+
}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.create(filename, images, width, height)
|
22
|
+
target = ChunkyPNG::Image.new(width, height, ChunkyPNG::Color::TRANSPARENT)
|
23
|
+
images.each do |image|
|
24
|
+
target.compose!(image[:image], image[:x], image[:y])
|
25
|
+
end
|
26
|
+
target.save(filename)
|
27
|
+
end
|
28
|
+
|
29
|
+
end # module ChunkyPng
|
30
|
+
end # module Library
|
31
|
+
end # module SpriteFactory
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'RMagick'
|
2
|
+
|
3
|
+
module SpriteFactory
|
4
|
+
module Library
|
5
|
+
module RMagick
|
6
|
+
|
7
|
+
VALID_EXTENSIONS = [:png, :jpg, :jpeg, :gif]
|
8
|
+
|
9
|
+
def self.load(files)
|
10
|
+
files.map do |filename|
|
11
|
+
image = Magick::Image.read(filename)[0]
|
12
|
+
{
|
13
|
+
:filename => filename,
|
14
|
+
:image => image,
|
15
|
+
:width => image.columns,
|
16
|
+
:height => image.rows
|
17
|
+
}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.create(filename, images, width, height)
|
22
|
+
target = Magick::Image.new(width,height)
|
23
|
+
target.opacity = Magick::MaxRGB
|
24
|
+
images.each do |image|
|
25
|
+
target.composite!(image[:image], image[:x], image[:y], Magick::SrcOverCompositeOp)
|
26
|
+
end
|
27
|
+
target.write(filename)
|
28
|
+
end
|
29
|
+
|
30
|
+
end # module RMagick
|
31
|
+
end # module Library
|
32
|
+
end # module SpriteFactory
|
@@ -0,0 +1,204 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
module SpriteFactory
|
4
|
+
class Runner
|
5
|
+
|
6
|
+
#----------------------------------------------------------------------------
|
7
|
+
|
8
|
+
attr :input
|
9
|
+
attr :config
|
10
|
+
|
11
|
+
def initialize(input, config = {})
|
12
|
+
@input = input.to_s[-1] == "/" ? input[0...-1] : input # gracefully ignore trailing slash on input directory name
|
13
|
+
@config = config
|
14
|
+
@config[:style] ||= SpriteFactory.style || :css
|
15
|
+
@config[:layout] ||= SpriteFactory.layout || :horizontal
|
16
|
+
@config[:library] ||= SpriteFactory.library || :rmagick
|
17
|
+
@config[:selector] ||= SpriteFactory.selector || 'img.'
|
18
|
+
@config[:csspath] ||= SpriteFactory.csspath
|
19
|
+
@config[:report] ||= SpriteFactory.report
|
20
|
+
end
|
21
|
+
|
22
|
+
#----------------------------------------------------------------------------
|
23
|
+
|
24
|
+
def run!(&block)
|
25
|
+
|
26
|
+
raise RuntimeError, "unknown layout #{layout_name}" if !Layout.respond_to?(layout_name)
|
27
|
+
raise RuntimeError, "unknown style #{style_name}" if !Style.respond_to?(style_name)
|
28
|
+
raise RuntimeError, "unknown library #{library_name}" if !Library.respond_to?(library_name)
|
29
|
+
|
30
|
+
raise RuntimeError, "input must be a single directory" if input.nil? || input.to_s.empty? || !File.directory?(input)
|
31
|
+
raise RuntimeError, "no output file specified" if output.nil? || output.to_s.empty?
|
32
|
+
raise RuntimeError, "no image files found" if image_files.empty?
|
33
|
+
|
34
|
+
raise RuntimeError, "set :width for fixed width, or :hpadding for horizontal padding, but not both." if width && !hpadding.zero?
|
35
|
+
raise RuntimeError, "set :height for fixed height, or :vpadding for vertical padding, but not both." if height && !vpadding.zero?
|
36
|
+
|
37
|
+
images = load_images
|
38
|
+
max = layout_images(images)
|
39
|
+
header = summary(images, max)
|
40
|
+
|
41
|
+
create_sprite(images, max[:width], max[:height])
|
42
|
+
|
43
|
+
css_file = File.open(output_style_file, "w+")
|
44
|
+
css_file.puts style_comment(header)
|
45
|
+
css_file.puts style(selector, css_path, images, &block)
|
46
|
+
css_file.puts IO.read(custom_style_file) if File.exists?(custom_style_file)
|
47
|
+
css_file.close
|
48
|
+
|
49
|
+
report(header)
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
#----------------------------------------------------------------------------
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def output
|
58
|
+
config[:output] || input
|
59
|
+
end
|
60
|
+
|
61
|
+
def selector
|
62
|
+
config[:selector]
|
63
|
+
end
|
64
|
+
|
65
|
+
def style_name
|
66
|
+
config[:style]
|
67
|
+
end
|
68
|
+
|
69
|
+
def layout_name
|
70
|
+
config[:layout]
|
71
|
+
end
|
72
|
+
|
73
|
+
def library_name
|
74
|
+
config[:library]
|
75
|
+
end
|
76
|
+
|
77
|
+
def hpadding
|
78
|
+
config[:hpadding] || config[:padding] || 0
|
79
|
+
end
|
80
|
+
|
81
|
+
def vpadding
|
82
|
+
config[:vpadding] || config[:padding] || 0
|
83
|
+
end
|
84
|
+
|
85
|
+
def width
|
86
|
+
config[:width]
|
87
|
+
end
|
88
|
+
|
89
|
+
def height
|
90
|
+
config[:height]
|
91
|
+
end
|
92
|
+
|
93
|
+
def output_image_file
|
94
|
+
"#{output}.png" if output
|
95
|
+
end
|
96
|
+
|
97
|
+
def output_style_file
|
98
|
+
"#{output}.#{style_name}" if output and style_name
|
99
|
+
end
|
100
|
+
|
101
|
+
def custom_style_file
|
102
|
+
File.join(input, File.basename(input) + ".#{style_name}")
|
103
|
+
end
|
104
|
+
|
105
|
+
def css_path
|
106
|
+
base = File.basename(output_image_file)
|
107
|
+
custom = config[:csspath]
|
108
|
+
if custom
|
109
|
+
if custom.is_a?(Proc)
|
110
|
+
custom.call(base) # allow custom path using a lambda
|
111
|
+
elsif custom.include?('$IMAGE')
|
112
|
+
custom.sub('$IMAGE', base) # allow custom path with token replacement
|
113
|
+
else
|
114
|
+
File.join(custom, base) # allow custom path with simple prepend
|
115
|
+
end
|
116
|
+
else
|
117
|
+
base # otherwise, just default to basename of the output image
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def image_files
|
122
|
+
return [] if input.nil?
|
123
|
+
valid_extensions = library::VALID_EXTENSIONS
|
124
|
+
expansions = Array(valid_extensions).map{|ext| File.join(input, "**", "*.#{ext}")}
|
125
|
+
Dir[*expansions].sort
|
126
|
+
end
|
127
|
+
|
128
|
+
#----------------------------------------------------------------------------
|
129
|
+
|
130
|
+
def library
|
131
|
+
@library ||= Library.send(library_name)
|
132
|
+
end
|
133
|
+
|
134
|
+
def load_images
|
135
|
+
images = library.load(image_files)
|
136
|
+
images.each do |i|
|
137
|
+
i[:name] = File.basename(i[:filename])
|
138
|
+
i[:ext] = File.extname(i[:name])
|
139
|
+
i[:name] = i[:name][0...-i[:ext].length] unless i[:ext].empty?
|
140
|
+
|
141
|
+
raise RuntimeError, "image #{i[:name]} does not fit within a fixed width of #{width}" if width && (width < i[:width])
|
142
|
+
raise RuntimeError, "image #{i[:name]} does not fit within a fixed height of #{height}" if height && (height < i[:height])
|
143
|
+
end
|
144
|
+
images
|
145
|
+
end
|
146
|
+
|
147
|
+
def create_sprite(images, width, height)
|
148
|
+
library.create(output_image_file, images, width, height)
|
149
|
+
end
|
150
|
+
|
151
|
+
#----------------------------------------------------------------------------
|
152
|
+
|
153
|
+
def layout_images(images)
|
154
|
+
Layout.send(layout_name, images, :width => width, :height => height, :hpadding => hpadding, :vpadding => vpadding)
|
155
|
+
end
|
156
|
+
|
157
|
+
#----------------------------------------------------------------------------
|
158
|
+
|
159
|
+
def style(selector, path, images, &block)
|
160
|
+
defaults = Style.generate(style_name, selector, path, images) # must call, even if custom block is given, because it stashes generated css style into image[:style] attributes
|
161
|
+
if block_given?
|
162
|
+
yield images.inject({}) {|h,i| h[i[:name].to_sym] = i; h} # provide custom rule builder a hash by image name
|
163
|
+
else
|
164
|
+
defaults
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def style_comment(comment)
|
169
|
+
Style.comment(style_name, comment)
|
170
|
+
end
|
171
|
+
|
172
|
+
#----------------------------------------------------------------------------
|
173
|
+
|
174
|
+
def summary(images, max)
|
175
|
+
return <<-EOF
|
176
|
+
|
177
|
+
Creating a sprite from following images:
|
178
|
+
\n#{images.map{|i| " #{report_path(i[:filename])} (#{i[:width]}x#{i[:height]})" }.join("\n")}
|
179
|
+
|
180
|
+
Output files:
|
181
|
+
#{report_path(output_image_file)}
|
182
|
+
#{report_path(output_style_file)}
|
183
|
+
|
184
|
+
Output size:
|
185
|
+
#{max[:width]}x#{max[:height]}
|
186
|
+
|
187
|
+
EOF
|
188
|
+
end
|
189
|
+
|
190
|
+
def report(msg)
|
191
|
+
puts msg if config[:report]
|
192
|
+
end
|
193
|
+
|
194
|
+
def report_path(path) # always report paths relative to . to avoid machine specific information in report (to avoid DIFF issues in tests and version control)
|
195
|
+
@cwd ||= Pathname.new(File.expand_path('.'))
|
196
|
+
path = Pathname.new(path)
|
197
|
+
path = path.relative_path_from(@cwd) if path.absolute?
|
198
|
+
path.to_s
|
199
|
+
end
|
200
|
+
|
201
|
+
#----------------------------------------------------------------------------
|
202
|
+
|
203
|
+
end # class Runner
|
204
|
+
end # module SpriteFactory
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module SpriteFactory
|
2
|
+
module Style
|
3
|
+
|
4
|
+
#----------------------------------------------------------------------------
|
5
|
+
|
6
|
+
def self.css(selector, name, attributes)
|
7
|
+
"#{selector}#{name} { #{css_style(attributes)}; }"
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.css_style(attributes)
|
11
|
+
attributes.join("; ")
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.css_comment(comment)
|
15
|
+
return "/*\n#{comment}\n*/"
|
16
|
+
end
|
17
|
+
|
18
|
+
#----------------------------------------------------------------------------
|
19
|
+
|
20
|
+
def self.sass(selector, name, attributes)
|
21
|
+
"#{selector}#{name}\n" + sass_style(attributes)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.sass_style(attributes)
|
25
|
+
attributes.map{|a| " #{a}"}.join("\n") + "\n"
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.sass_comment(comment)
|
29
|
+
return "/* #{comment.rstrip} */" # SASS has peculiar indenting requirements in order to recognise closing block comment
|
30
|
+
end
|
31
|
+
|
32
|
+
#----------------------------------------------------------------------------
|
33
|
+
|
34
|
+
def self.generate(style_name, selector, path, images)
|
35
|
+
styles = []
|
36
|
+
images.each do |image|
|
37
|
+
attr = [
|
38
|
+
"width: #{image[:cssw]}px",
|
39
|
+
"height: #{image[:cssh]}px",
|
40
|
+
"background: url(#{path}) #{-image[:cssx]}px #{-image[:cssy]}px no-repeat"
|
41
|
+
]
|
42
|
+
image[:style] = send("#{style_name}_style", attr) # make pure style available for (optional) custom rule generators (see usage of yield inside Runner#style)
|
43
|
+
styles << send(style_name, selector, image[:name], attr)
|
44
|
+
end
|
45
|
+
styles << ""
|
46
|
+
styles.join("\n")
|
47
|
+
end
|
48
|
+
|
49
|
+
#----------------------------------------------------------------------------
|
50
|
+
|
51
|
+
def self.comment(style_name, comment)
|
52
|
+
send("#{style_name}_comment", comment)
|
53
|
+
end
|
54
|
+
|
55
|
+
#----------------------------------------------------------------------------
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$LOAD_PATH.push File.expand_path("lib", File.dirname(__FILE__))
|
3
|
+
require 'sprite_factory'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
|
7
|
+
s.name = "sprite-factory"
|
8
|
+
s.version = SpriteFactory::VERSION
|
9
|
+
s.platform = Gem::Platform::RUBY
|
10
|
+
s.authors = ["Jake Gordon"]
|
11
|
+
s.email = ["jake@codeincomplete.com"]
|
12
|
+
s.homepage = "https://github.com/jakesgordon/sprite-factory"
|
13
|
+
s.summary = SpriteFactory::SUMMARY
|
14
|
+
s.description = SpriteFactory::DESCRIPTION
|
15
|
+
|
16
|
+
s.add_development_dependency 'rmagick'
|
17
|
+
s.add_development_dependency 'chunky_png'
|
18
|
+
|
19
|
+
s.files = `git ls-files`.split("\n")
|
20
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
21
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
22
|
+
s.require_paths = ["lib"]
|
23
|
+
|
24
|
+
end
|
Binary file
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
this file is only here because git can't deal with empty directories (uck)
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,22 @@
|
|
1
|
+
/*
|
2
|
+
|
3
|
+
Creating a sprite from following images:
|
4
|
+
|
5
|
+
test/images/custom/running.png (46x25)
|
6
|
+
test/images/custom/stopped.png (46x25)
|
7
|
+
|
8
|
+
Output files:
|
9
|
+
test/images/custom.png
|
10
|
+
test/images/custom.css
|
11
|
+
|
12
|
+
Output size:
|
13
|
+
92x25
|
14
|
+
|
15
|
+
|
16
|
+
*/
|
17
|
+
div.running img.button { cursor: pointer; width: 46px; height: 25px; background: url(custom.png) 0px 0px no-repeat }
|
18
|
+
div.stopped img.button { cursor: pointer; width: 46px; height: 25px; background: url(custom.png) -46px 0px no-repeat }
|
19
|
+
div.running span.running { display: inline; }
|
20
|
+
div.running span.stopped { display: none; }
|
21
|
+
div.stopped span.running { display: none; }
|
22
|
+
div.stopped span.stopped { display: inline; }
|
Binary file
|
@@ -0,0 +1,22 @@
|
|
1
|
+
/*
|
2
|
+
|
3
|
+
Creating a sprite from following images:
|
4
|
+
|
5
|
+
test/images/formats/alice.gif (50x50)
|
6
|
+
test/images/formats/monkey.gif (50x50)
|
7
|
+
test/images/formats/spies.jpg (150x92)
|
8
|
+
test/images/formats/thief.png (50x50)
|
9
|
+
|
10
|
+
Output files:
|
11
|
+
test/images/formats.png
|
12
|
+
test/images/formats.css
|
13
|
+
|
14
|
+
Output size:
|
15
|
+
300x92
|
16
|
+
|
17
|
+
|
18
|
+
*/
|
19
|
+
img.alice { width: 50px; height: 50px; background: url(formats.png) 0px -21px no-repeat; }
|
20
|
+
img.monkey { width: 50px; height: 50px; background: url(formats.png) -50px -21px no-repeat; }
|
21
|
+
img.spies { width: 150px; height: 92px; background: url(formats.png) -100px 0px no-repeat; }
|
22
|
+
img.thief { width: 50px; height: 50px; background: url(formats.png) -250px -21px no-repeat; }
|
Binary file
|
@@ -0,0 +1,135 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta charset='utf-8' />
|
5
|
+
<title>Test page for sprite factory</title>
|
6
|
+
<link href='regular.css' rel='stylesheet' type='text/css' media='screen'></link>
|
7
|
+
<link href='regular.horizontal.css' rel='stylesheet' type='text/css' media='screen'></link>
|
8
|
+
<link href='regular.vertical.css' rel='stylesheet' type='text/css' media='screen'></link>
|
9
|
+
<link href='regular.padded.css' rel='stylesheet' type='text/css' media='screen'></link>
|
10
|
+
<link href='regular.fixed.css' rel='stylesheet' type='text/css' media='screen'></link>
|
11
|
+
<link href='regular.sassy.css' rel='stylesheet' type='text/css' media='screen'></link>
|
12
|
+
<link href='irregular.css' rel='stylesheet' type='text/css' media='screen'></link>
|
13
|
+
<link href='irregular.horizontal.css' rel='stylesheet' type='text/css' media='screen'></link>
|
14
|
+
<link href='irregular.vertical.css' rel='stylesheet' type='text/css' media='screen'></link>
|
15
|
+
<link href='irregular.padded.css' rel='stylesheet' type='text/css' media='screen'></link>
|
16
|
+
<link href='irregular.fixed.css' rel='stylesheet' type='text/css' media='screen'></link>
|
17
|
+
<link href='irregular.sassy.css' rel='stylesheet' type='text/css' media='screen'></link>
|
18
|
+
<link href='custom.css' rel='stylesheet' type='text/css' media='screen'></link>
|
19
|
+
<link href='formats.css' rel='stylesheet' type='text/css' media='screen'></link>
|
20
|
+
<style>
|
21
|
+
img { border: 1px solid red; }
|
22
|
+
</style>
|
23
|
+
</head>
|
24
|
+
<body>
|
25
|
+
|
26
|
+
<h1>Regular (defaults)</h1>
|
27
|
+
<img src='s.gif' class='regular1'>
|
28
|
+
<img src='s.gif' class='regular2'>
|
29
|
+
<img src='s.gif' class='regular3'>
|
30
|
+
<img src='s.gif' class='regular4'>
|
31
|
+
<img src='s.gif' class='regular5'>
|
32
|
+
|
33
|
+
<h1>Regular (horizontal)</h1>
|
34
|
+
<img src='s.gif' class='horizontal_regular1'>
|
35
|
+
<img src='s.gif' class='horizontal_regular2'>
|
36
|
+
<img src='s.gif' class='horizontal_regular3'>
|
37
|
+
<img src='s.gif' class='horizontal_regular4'>
|
38
|
+
<img src='s.gif' class='horizontal_regular5'>
|
39
|
+
|
40
|
+
<h1>Regular (vertical)</h1>
|
41
|
+
<img src='s.gif' class='vertical_regular1'><br>
|
42
|
+
<img src='s.gif' class='vertical_regular2'><br>
|
43
|
+
<img src='s.gif' class='vertical_regular3'><br>
|
44
|
+
<img src='s.gif' class='vertical_regular4'><br>
|
45
|
+
<img src='s.gif' class='vertical_regular5'><br>
|
46
|
+
|
47
|
+
<h1>Regular (padded)</h1>
|
48
|
+
<img src='s.gif' class='padded_regular1'>
|
49
|
+
<img src='s.gif' class='padded_regular2'>
|
50
|
+
<img src='s.gif' class='padded_regular3'>
|
51
|
+
<img src='s.gif' class='padded_regular4'>
|
52
|
+
<img src='s.gif' class='padded_regular5'>
|
53
|
+
|
54
|
+
<h1>Regular (fixed)</h1>
|
55
|
+
<img src='s.gif' class='fixed_regular1'>
|
56
|
+
<img src='s.gif' class='fixed_regular2'>
|
57
|
+
<img src='s.gif' class='fixed_regular3'>
|
58
|
+
<img src='s.gif' class='fixed_regular4'>
|
59
|
+
<img src='s.gif' class='fixed_regular5'>
|
60
|
+
|
61
|
+
<h1>Regular (sassy)</h1>
|
62
|
+
<img src='s.gif' class='sassy_regular1'>
|
63
|
+
<img src='s.gif' class='sassy_regular2'>
|
64
|
+
<img src='s.gif' class='sassy_regular3'>
|
65
|
+
<img src='s.gif' class='sassy_regular4'>
|
66
|
+
<img src='s.gif' class='sassy_regular5'>
|
67
|
+
|
68
|
+
<h1>Irregular (defaults)</h1>
|
69
|
+
<img src='s.gif' class='irregular1'>
|
70
|
+
<img src='s.gif' class='irregular2'>
|
71
|
+
<img src='s.gif' class='irregular3'>
|
72
|
+
<img src='s.gif' class='irregular4'>
|
73
|
+
<img src='s.gif' class='irregular5'>
|
74
|
+
|
75
|
+
<h1>Irregular (horizontal)</h1>
|
76
|
+
<img src='s.gif' class='horizontal_irregular1'>
|
77
|
+
<img src='s.gif' class='horizontal_irregular2'>
|
78
|
+
<img src='s.gif' class='horizontal_irregular3'>
|
79
|
+
<img src='s.gif' class='horizontal_irregular4'>
|
80
|
+
<img src='s.gif' class='horizontal_irregular5'>
|
81
|
+
|
82
|
+
<h1>Irregular (vertical)</h1>
|
83
|
+
<img src='s.gif' class='vertical_irregular1'><br>
|
84
|
+
<img src='s.gif' class='vertical_irregular2'><br>
|
85
|
+
<img src='s.gif' class='vertical_irregular3'><br>
|
86
|
+
<img src='s.gif' class='vertical_irregular4'><br>
|
87
|
+
<img src='s.gif' class='vertical_irregular5'><br>
|
88
|
+
|
89
|
+
<h1>Irregular (padded)</h1>
|
90
|
+
<img src='s.gif' class='padded_irregular1'>
|
91
|
+
<img src='s.gif' class='padded_irregular2'>
|
92
|
+
<img src='s.gif' class='padded_irregular3'>
|
93
|
+
<img src='s.gif' class='padded_irregular4'>
|
94
|
+
<img src='s.gif' class='padded_irregular5'>
|
95
|
+
|
96
|
+
<h1>Irregular (fixed)</h1>
|
97
|
+
<img src='s.gif' class='fixed_irregular1'>
|
98
|
+
<img src='s.gif' class='fixed_irregular2'>
|
99
|
+
<img src='s.gif' class='fixed_irregular3'>
|
100
|
+
<img src='s.gif' class='fixed_irregular4'>
|
101
|
+
<img src='s.gif' class='fixed_irregular5'>
|
102
|
+
|
103
|
+
<h1>Irregular (sassy)</h1>
|
104
|
+
<img src='s.gif' class='sassy_irregular1'>
|
105
|
+
<img src='s.gif' class='sassy_irregular2'>
|
106
|
+
<img src='s.gif' class='sassy_irregular3'>
|
107
|
+
<img src='s.gif' class='sassy_irregular4'>
|
108
|
+
<img src='s.gif' class='sassy_irregular5'>
|
109
|
+
|
110
|
+
<h1>Custom</h1>
|
111
|
+
<div class='running' id='timer'>
|
112
|
+
<img src='s.gif' class='button' onclick="SpriteFactory.toggleTimer();">
|
113
|
+
<span class='running'>running</span>
|
114
|
+
<span class='stopped'>stopped</span>
|
115
|
+
</div>
|
116
|
+
|
117
|
+
<h1>Other Formats</h1>
|
118
|
+
<img src='s.gif' class='alice'>
|
119
|
+
<img src='s.gif' class='monkey'>
|
120
|
+
<img src='s.gif' class='spies'>
|
121
|
+
<img src='s.gif' class='thief'>
|
122
|
+
|
123
|
+
<script>
|
124
|
+
SpriteFactory = {
|
125
|
+
toggleTimer: function() {
|
126
|
+
var timer = document.getElementById('timer');
|
127
|
+
if (timer) {
|
128
|
+
timer.setAttribute('class', timer.getAttribute('class') == 'running' ? 'stopped' : 'running');
|
129
|
+
}
|
130
|
+
}
|
131
|
+
}
|
132
|
+
</script>
|
133
|
+
|
134
|
+
</body>
|
135
|
+
</html>
|