geo_pattern 1.2.1 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6321ec629bed93b949fb0af35e1930beb4c4bc17
4
+ data.tar.gz: 83b4d012dbf6d98585d2204da0f5f539baab5dd6
5
+ SHA512:
6
+ metadata.gz: a2f516f74c4485678517044c9e726ae83ff851a5d0e3c71882eb0379f860f3a0b04c71ba32a93af85cfc101c009f8787bbe303f8638e2492bb8cd8b589207ada
7
+ data.tar.gz: ef40eefa6ff0cde718bec5916ab93eab6c84b843d0eb324d24a10ae406317765befbe04cc9b798bb122c2f7f6b750e8a25f07e57736e357ad9f00f4611f98d23
data/README.md CHANGED
@@ -1,10 +1,13 @@
1
+ [![](http://img.shields.io/gem/v/geo_pattern.svg?style=flat)](http://rubygems.org/gems/geo_pattern)
2
+ [![](http://img.shields.io/gem/dt/geo_pattern.svg?style=flat)](http://rubygems.org/gems/geo_pattern)
3
+
1
4
  # GeoPattern
2
5
 
3
6
  Generate beautiful tiling SVG patterns from a string. The string is converted into a SHA and a color and pattern are determined based on the values in the hash. The color is determined by shifting the hue and saturation from a default (or passed in) base color. One of 16 patterns is used (or you can specify one) and the sizing of the pattern elements is also determined by the hash values.
4
7
 
5
8
  You can use the generated pattern as the `background-image` for a container. Using the `base64` representation of the pattern still results in SVG rendering, so it looks great on retina displays.
6
9
 
7
- See the [GitHub Guides](http://guides.github.com) site as an example of this library in action.
10
+ See the [GitHub Guides](http://guides.github.com) site and the [Explore section of GitHub](https://github.com/explore) are examples of this library in action. Brandon Mills has put together an awesome [live preview page](http://btmills.github.io/geopattern/geopattern.html) that's built on his Javascript port.
8
11
 
9
12
  ## Installation
10
13
 
@@ -24,93 +27,109 @@ Or install it yourself as:
24
27
 
25
28
  Make a new pattern:
26
29
 
27
- pattern = GeoPattern.generate("Mastering Markdown")
30
+ ```ruby
31
+ pattern = GeoPattern.generate("Mastering Markdown")
32
+ ```
28
33
 
29
34
  To specify a base background color (with a hue and saturation that adjusts depending on the string):
30
35
 
31
- pattern = GeoPattern.generate("Mastering Markdown", {:base_color => "#fc0"})
36
+ ```ruby
37
+ pattern = GeoPattern.generate("Mastering Markdown", {:base_color => "#fc0"})
38
+ ```
32
39
 
33
40
  To use a specific background color (w/o any hue or saturation adjustments):
34
41
 
35
- pattern = GeoPattern.generate("Mastering Markdown", {:color => "#fc0"})
42
+ ```ruby
43
+ pattern = GeoPattern.generate("Mastering Markdown", {:color => "#fc0"})
44
+ ```
36
45
 
37
46
  To use a specific [pattern generator](#available-patterns):
38
47
 
39
- pattern = GeoPattern.generate("Mastering Markdown", {:generator => "sine_waves"})
48
+ ```ruby
49
+ pattern = GeoPattern.generate("Mastering Markdown", {:generator => GeoPattern::SineWavePattern})
50
+ ```
40
51
 
41
52
  Get the SVG string:
42
53
 
43
- puts pattern.svg_string
44
- # => <svg xmlns="http://www.w3.org/2000/svg" ...
54
+ ```ruby
55
+ puts pattern.svg_string
56
+ # => <svg xmlns="http://www.w3.org/2000/svg" ...
57
+ ```
45
58
 
46
59
  Get the Base64 encoded string:
47
60
 
48
- puts pattern.base64_string
49
- # => PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC...
61
+ ```ruby
62
+ puts pattern.base64_string
63
+ # => PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC...
64
+ ```
50
65
 
51
66
  You can then use this string to set the background:
52
67
 
53
- <div style="background-image: <%=pattern.uri_image%>"></div>
68
+ ```html
69
+ <div style="background-image: <%= pattern.uri_image %>"></div>
70
+ ```
54
71
 
55
72
  ## Available patterns
56
73
 
57
- ### octogons
74
+ *Note: As of version `1.3.0`, string references (e.g. `overlapping_circles`) are deprecated in favor of class references (e.g. `GeoPattern::OverlappingCirclesPattern`).*
75
+
76
+ ### GeoPattern::OctagonPattern
58
77
 
59
78
  ![](http://jasonlong.github.io/geo_pattern/examples/octogons.png)
60
79
 
61
- ### overlapping_circles
80
+ ### GeoPattern::OverlappingCirclesPattern
62
81
 
63
82
  ![](http://jasonlong.github.io/geo_pattern/examples/overlapping_circles.png)
64
83
 
65
- ### plus_signs
84
+ ### GeoPattern::PlusSignPattern
66
85
 
67
86
  ![](http://jasonlong.github.io/geo_pattern/examples/plus_signs.png)
68
87
 
69
- ### xes
88
+ ### GeoPattern::XesPattern
70
89
 
71
90
  ![](http://jasonlong.github.io/geo_pattern/examples/xes.png)
72
91
 
73
- ### sine_waves
92
+ ### GeoPattern::SineWavePattern
74
93
 
75
94
  ![](http://jasonlong.github.io/geo_pattern/examples/sine_waves.png)
76
95
 
77
- ### hexagons
96
+ ### GeoPattern::HexagonPattern
78
97
 
79
98
  ![](http://jasonlong.github.io/geo_pattern/examples/hexagons.png)
80
99
 
81
- ### overlapping_rings
100
+ ### GeoPattern::OverlappingCirclesPattern
82
101
 
83
102
  ![](http://jasonlong.github.io/geo_pattern/examples/overlapping_rings.png)
84
103
 
85
- ### plaid
104
+ ### GeoPattern::PlaidPattern
86
105
 
87
106
  ![](http://jasonlong.github.io/geo_pattern/examples/plaid.png)
88
107
 
89
- ### triangles
108
+ ### GeoPattern::TrianglePattern
90
109
 
91
110
  ![](http://jasonlong.github.io/geo_pattern/examples/triangles.png)
92
111
 
93
- ### squares
112
+ ### GeoPattern::SquarePattern
94
113
 
95
114
  ![](http://jasonlong.github.io/geo_pattern/examples/squares.png)
96
115
 
97
- ### nested_squares
116
+ ### GeoPattern::NestedSquaresPattern
98
117
 
99
118
  ![](http://jasonlong.github.io/geo_pattern/examples/nested_squares.png)
100
119
 
101
- ### mosaic_squares
120
+ ### GeoPattern::MosaicSquaresPattern
102
121
 
103
122
  ![](http://jasonlong.github.io/geo_pattern/examples/mosaic_squares.png)
104
123
 
105
- ### concentric_circles
124
+ ### GeoPattern::ConcentricCirclesPattern
106
125
 
107
126
  ![](http://jasonlong.github.io/geo_pattern/examples/concentric_circles.png)
108
127
 
109
- ### diamonds
128
+ ### GeoPattern::DiamondPattern
110
129
 
111
130
  ![](http://jasonlong.github.io/geo_pattern/examples/diamonds.png)
112
131
 
113
- ### tessellation
132
+ ### GeoPattern::TessellationPattern
114
133
 
115
134
  ![](http://jasonlong.github.io/geo_pattern/examples/tessellation.png)
116
135
 
@@ -125,11 +144,17 @@ You can then use this string to set the background:
125
144
 
126
145
  ## Ports
127
146
 
128
- Brandon Mills is working on completing my original Javascript version:
147
+ JavaScript port by Brandon Mills:
129
148
  https://github.com/btmills/geopatterns-js
130
149
 
131
- Bryan Veloso is porting the library to Python:
150
+ Python port by Bryan Veloso:
132
151
  https://github.com/bryanveloso/geopatterns
133
152
 
134
- Anand Capur is porting the library to PHP:
153
+ PHP port by Anand Capur:
135
154
  https://github.com/redeyeventures/geopattern-php
155
+
156
+ Go port by Pravendra Singh:
157
+ https://github.com/pravj/geo_pattern
158
+
159
+ CoffeeScript port by Aleks (muchweb):
160
+ https://github.com/muchweb/geo-pattern-coffee
data/lib/geo_pattern.rb CHANGED
@@ -1,9 +1,10 @@
1
1
  require "geo_pattern/version"
2
2
  require "geo_pattern/svg"
3
- require "geo_pattern/pattern"
3
+ require 'geo_pattern/pattern/pattern_helpers'
4
+ require "geo_pattern/pattern_generator"
4
5
 
5
6
  module GeoPattern
6
- def self.generate(string=Time.now.to_s, opts={})
7
- GeoPattern::Pattern.new(string, opts)
7
+ def self.generate(string=Time.now, opts={})
8
+ GeoPattern::PatternGenerator.new(string.to_s, opts)
8
9
  end
9
10
  end
@@ -0,0 +1,47 @@
1
+ module GeoPattern
2
+ class BasePattern < Struct.new(:svg, :hash)
3
+ FILL_COLOR_DARK = "#222"
4
+ FILL_COLOR_LIGHT = "#ddd"
5
+ STROKE_COLOR = "#000"
6
+ STROKE_OPACITY = 0.02
7
+ OPACITY_MIN = 0.02
8
+ OPACITY_MAX = 0.15
9
+
10
+ # Public: mutate the given `svg` object with a rendered pattern
11
+ #
12
+ # Note: this method _must_ be implemented by sub-
13
+ # classes.
14
+ #
15
+ # svg - the SVG container
16
+ #
17
+ # Returns a reference to the same `svg` object
18
+ # only this time with more patterns.
19
+ def render_to_svg
20
+ raise NotImplementedError
21
+ end
22
+
23
+ def hex_val(index, len)
24
+ PatternHelpers.hex_val(hash, index, len)
25
+ end
26
+
27
+ def fill_color(val)
28
+ (val.even?) ? FILL_COLOR_LIGHT : FILL_COLOR_DARK
29
+ end
30
+
31
+ def opacity(val)
32
+ map(val, 0, 15, OPACITY_MIN, OPACITY_MAX)
33
+ end
34
+
35
+ def map(value, v_min, v_max, d_min, d_max)
36
+ PatternHelpers.map(value, v_min, v_max, d_min, d_max)
37
+ end
38
+
39
+ protected
40
+ def build_plus_shape(square_size)
41
+ [
42
+ "rect(#{square_size},0,#{square_size},#{square_size * 3})",
43
+ "rect(0, #{square_size},#{square_size * 3},#{square_size})"
44
+ ]
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,45 @@
1
+ module GeoPattern
2
+ class ChevronPattern < BasePattern
3
+ def render_to_svg
4
+ chevron_width = map(hex_val(0, 1), 0, 15, 30, 80)
5
+ chevron_height = map(hex_val(0, 1), 0, 15, 30, 80)
6
+ chevron = build_chevron_shape(chevron_width, chevron_height)
7
+
8
+ svg.set_width(chevron_width * 6)
9
+ svg.set_height(chevron_height * 6 * 0.66)
10
+
11
+ i = 0
12
+ for y in 0..5
13
+ for x in 0..5
14
+ val = hex_val(i, 1)
15
+ opacity = opacity(val)
16
+ fill = fill_color(val)
17
+
18
+ styles = {
19
+ "stroke" => STROKE_COLOR,
20
+ "stroke-opacity" => STROKE_OPACITY,
21
+ "fill" => fill,
22
+ "fill-opacity" => opacity,
23
+ "stroke-width" => 1
24
+ }
25
+
26
+ svg.group(chevron, styles.merge({"transform" => "translate(#{x*chevron_width},#{y*chevron_height*0.66 - chevron_height/2})"}))
27
+
28
+ # Add an extra row at the end that matches the first row, for tiling.
29
+ if (y == 0)
30
+ svg.group(chevron, styles.merge({"transform" => "translate(#{x*chevron_width},#{6*chevron_height*0.66 - chevron_height/2})"}))
31
+ end
32
+ i += 1
33
+ end
34
+ end
35
+ end
36
+
37
+ def build_chevron_shape(width, height)
38
+ e = height * 0.66
39
+ [
40
+ %Q{polyline("0,0,#{width/2},#{height-e},#{width/2},#{height},0,#{e},0,0")},
41
+ %Q{polyline("#{width/2},#{height-e},#{width},0,#{width},#{e},#{width/2},#{height},#{width/2},#{height-e}")}
42
+ ]
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,47 @@
1
+ module GeoPattern
2
+ class ConcentricCirclesPattern < BasePattern
3
+ def render_to_svg
4
+ scale = hex_val(0, 1)
5
+ ring_size = map(scale, 0, 15, 10, 60)
6
+ stroke_width = ring_size / 5
7
+
8
+ svg.set_width((ring_size + stroke_width) * 6)
9
+ svg.set_height((ring_size + stroke_width) * 6)
10
+
11
+ i = 0
12
+ for y in 0..5
13
+ for x in 0..5
14
+ val = hex_val(i, 1)
15
+ opacity = opacity(val)
16
+ fill = fill_color(val)
17
+
18
+ svg.circle(
19
+ x*ring_size + x*stroke_width + (ring_size + stroke_width)/2,
20
+ y*ring_size + y*stroke_width + (ring_size + stroke_width)/2,
21
+ ring_size/2, {
22
+ "fill" => "none",
23
+ "stroke" => fill,
24
+ "style" => {
25
+ "opacity" => opacity,
26
+ "stroke-width" => "#{stroke_width}px"
27
+ }
28
+ })
29
+
30
+ val = hex_val(39-i, 1)
31
+ opacity = opacity(val)
32
+ fill = fill_color(val)
33
+
34
+ svg.circle(
35
+ x*ring_size + x*stroke_width + (ring_size + stroke_width)/2,
36
+ y*ring_size + y*stroke_width + (ring_size + stroke_width)/2,
37
+ ring_size/4, {
38
+ "fill" => fill,
39
+ "fill-opacity" => opacity
40
+ })
41
+
42
+ i += 1
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,56 @@
1
+ module GeoPattern
2
+ class DiamondPattern < BasePattern
3
+ def render_to_svg
4
+ diamond_width = map(hex_val(0, 1), 0, 15, 10, 50)
5
+ diamond_height = map(hex_val(1, 1), 0, 15, 10, 50)
6
+ diamond = build_diamond_shape(diamond_width, diamond_height)
7
+
8
+ svg.set_width(diamond_width * 6)
9
+ svg.set_height(diamond_height * 3)
10
+
11
+ i = 0
12
+ for y in 0..5
13
+ for x in 0..5
14
+ val = hex_val(i, 1)
15
+ opacity = opacity(val)
16
+ fill = fill_color(val)
17
+
18
+ styles = {
19
+ "fill" => fill,
20
+ "fill-opacity" => opacity,
21
+ "stroke" => STROKE_COLOR,
22
+ "stroke-opacity" => STROKE_OPACITY
23
+ }
24
+
25
+ dx = (y % 2 == 0) ? 0 : diamond_width / 2
26
+
27
+ svg.polyline(diamond, styles.merge({
28
+ "transform" => "translate(#{x*diamond_width - diamond_width/2 + dx}, #{diamond_height/2*y - diamond_height/2})"}))
29
+
30
+ # Add an extra one at top-right, for tiling.
31
+ if (x == 0)
32
+ svg.polyline(diamond, styles.merge({
33
+ "transform" => "translate(#{6*diamond_width - diamond_width/2 + dx}, #{diamond_height/2*y - diamond_height/2})"}))
34
+ end
35
+
36
+ # Add an extra row at the end that matches the first row, for tiling.
37
+ if (y == 0)
38
+ svg.polyline(diamond, styles.merge({
39
+ "transform" => "translate(#{x*diamond_width - diamond_width/2 + dx}, #{diamond_height/2*6 - diamond_height/2})"}))
40
+ end
41
+
42
+ # Add an extra one at bottom-right, for tiling.
43
+ if (x == 0 and y == 0)
44
+ svg.polyline(diamond, styles.merge({
45
+ "transform" => "translate(#{6*diamond_width - diamond_width/2 + dx}, #{diamond_height/2*6 - diamond_height/2})"}))
46
+ end
47
+ i += 1
48
+ end
49
+ end
50
+ end
51
+
52
+ def build_diamond_shape(width, height)
53
+ "#{width/2}, 0, #{width}, #{height/2}, #{width/2}, #{height}, 0, #{height/2}"
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,57 @@
1
+ module GeoPattern
2
+ class HexagonPattern < BasePattern
3
+ def render_to_svg
4
+ scale = hex_val(0, 1)
5
+ side_length = map(scale, 0, 15, 8, 60)
6
+ hex_height = side_length * Math.sqrt(3)
7
+ hex_width = side_length * 2
8
+ hex = build_hexagon_shape(side_length)
9
+
10
+ svg.set_width((hex_width * 3) + (side_length * 3))
11
+ svg.set_height(hex_height * 6)
12
+
13
+ i = 0
14
+ for y in 0..5
15
+ for x in 0..5
16
+ val = hex_val(i, 1)
17
+ dy = x % 2 == 0 ? y*hex_height : y*hex_height + hex_height/2
18
+ opacity = opacity(val)
19
+ fill = fill_color(val)
20
+
21
+ styles = {
22
+ "fill" => fill,
23
+ "fill-opacity" => opacity,
24
+ "stroke" => STROKE_COLOR,
25
+ "stroke-opacity" => STROKE_OPACITY
26
+ }
27
+
28
+ svg.polyline(hex, styles.merge({"transform" => "translate(#{x*side_length*1.5 - hex_width/2}, #{dy - hex_height/2})"}))
29
+
30
+ # Add an extra one at top-right, for tiling.
31
+ if (x == 0)
32
+ svg.polyline(hex, styles.merge({"transform" => "translate(#{6*side_length*1.5 - hex_width/2}, #{dy - hex_height/2})"}))
33
+ end
34
+
35
+ # Add an extra row at the end that matches the first row, for tiling.
36
+ if (y == 0)
37
+ dy = x % 2 == 0 ? 6*hex_height : 6*hex_height + hex_height/2;
38
+ svg.polyline(hex, styles.merge({"transform" => "translate(#{x*side_length*1.5 - hex_width/2}, #{dy - hex_height/2})"}))
39
+ end
40
+
41
+ # Add an extra one at bottom-right, for tiling.
42
+ if (x == 0 && y == 0)
43
+ svg.polyline(hex, styles.merge({"transform" => "translate(#{6*side_length*1.5 - hex_width/2}, #{5*hex_height + hex_height/2})"}))
44
+ end
45
+ i += 1
46
+ end
47
+ end
48
+ end
49
+
50
+ def build_hexagon_shape(sideLength)
51
+ c = sideLength
52
+ a = c/2
53
+ b = Math.sin(60 * Math::PI / 180)*c
54
+ "0,#{b},#{a},0,#{a+c},0,#{2*c},#{b},#{a+c},#{2*b},#{a},#{2*b},0,#{b}"
55
+ end
56
+ end
57
+ end