rubyvis 0.3.4 → 0.3.5
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/History.txt +8 -0
- data/Manifest.txt +7 -0
- data/README.txt +23 -6
- data/examples/2_medium/horizon.rb +58 -0
- data/examples/5_pv_hierarchies/dendogram.rb +2 -2
- data/examples/6_pv_networks/arc.rb +32 -0
- data/examples/6_pv_networks/miserables_data.rb +348 -0
- data/lib/rubyvis.rb +1 -1
- data/lib/rubyvis/color/color.rb +32 -34
- data/lib/rubyvis/format/number.rb +1 -1
- data/lib/rubyvis/layout.rb +3 -2
- data/lib/rubyvis/layout/arc.rb +188 -0
- data/lib/rubyvis/layout/horizon.rb +153 -0
- data/lib/rubyvis/mark/shorcut_methods.rb +29 -1
- data/lib/rubyvis/scene/svg_panel.rb +6 -4
- data/lib/rubyvis/sceneelement.rb +1 -1
- data/spec/color_spec.rb +79 -0
- data/spec/layout_horizon_spec.rb +78 -0
- data/spec/layout_stack_spec.rb +3 -5
- data/web/index.haml +20 -12
- metadata +11 -4
- metadata.gz.sig +0 -0
data/lib/rubyvis.rb
CHANGED
@@ -30,7 +30,7 @@ require 'rubyvis/mark/shorcut_methods'
|
|
30
30
|
module Rubyvis
|
31
31
|
@document=nil
|
32
32
|
# Rubyvis version
|
33
|
-
VERSION = '0.3.
|
33
|
+
VERSION = '0.3.5'
|
34
34
|
# Protovis API on which current Rubyvis is based
|
35
35
|
PROTOVIS_API_VERSION='3.3'
|
36
36
|
# You actually can do it! http://snipplr.com/view/2137/uses-for-infinity-in-ruby/
|
data/lib/rubyvis/color/color.rb
CHANGED
@@ -27,24 +27,24 @@ module Rubyvis
|
|
27
27
|
def self.color(format)
|
28
28
|
return format.rgb if format.respond_to? :rgb
|
29
29
|
if (format =~/([a-z]+)\((.*)\)/)
|
30
|
-
|
30
|
+
color_type,color_data=$1,$2
|
31
|
+
m2 = color_data.split(",")
|
31
32
|
a = 1
|
32
|
-
if ['hsla','rgba'].include?
|
33
|
+
if ['hsla','rgba'].include? color_type
|
33
34
|
a = m2[3].to_f
|
34
35
|
return Color.transparent if (a==0)
|
35
36
|
end
|
36
37
|
|
37
|
-
if ['hsla','hsl'].include?
|
38
|
-
h=m2[0].
|
39
|
-
s=m2[
|
40
|
-
l=m2[
|
41
|
-
return Color::Hsl.new(h,s,l,a).rgb
|
38
|
+
if ['hsla','hsl'].include? color_type
|
39
|
+
h=m2[0].to_i
|
40
|
+
s=m2[1].to_f / 100
|
41
|
+
l=m2[2].to_f / 100
|
42
|
+
return Color::Hsl.new(h,s,l,a).rgb
|
42
43
|
end
|
43
|
-
|
44
|
-
if ['rgba','rgb'].include?
|
44
|
+
|
45
|
+
if ['rgba','rgb'].include? color_type
|
45
46
|
parse=lambda {|c|
|
46
|
-
|
47
|
-
return (c[c.size-1]=='%') ? (f*2.55).round : f
|
47
|
+
(c[c.size-1,1]=='%') ? (c.to_f*2.55).round : c.to_i
|
48
48
|
}
|
49
49
|
r=parse.call(m2[0])
|
50
50
|
g=parse.call(m2[1])
|
@@ -69,7 +69,7 @@ module Rubyvis
|
|
69
69
|
g = format[3,2]
|
70
70
|
b = format[5,2]
|
71
71
|
end
|
72
|
-
return Rubyvis.rgb(r.to_i(16), g.to_i(16), b.to_i(16), 1)
|
72
|
+
return Rubyvis.rgb(r.to_i(16), g.to_i(16), b.to_i(16), 1)
|
73
73
|
end
|
74
74
|
|
75
75
|
# Otherwise, pass-through unsupported colors. */
|
@@ -292,14 +292,10 @@ module Rubyvis
|
|
292
292
|
@g=g
|
293
293
|
@a=a
|
294
294
|
@opacity=a
|
295
|
-
|
296
|
-
@color="rgb(#{r.to_i},#{g.to_i},#{b.to_i})"
|
297
|
-
else
|
298
|
-
@color="none"
|
299
|
-
end
|
295
|
+
@color= @a > 0 ? "rgb(#{r.to_i},#{g.to_i},#{b.to_i})" : "none"
|
300
296
|
end
|
301
297
|
def ==(v)
|
302
|
-
self.class==v.class and @r==v.r and @b==v.b and @g
|
298
|
+
self.class==v.class and @r==v.r and @b==v.b and @g==v.g and @a==v.a
|
303
299
|
end
|
304
300
|
|
305
301
|
# Constructs a new RGB color with the same green, blue and alpha channels
|
@@ -333,20 +329,20 @@ module Rubyvis
|
|
333
329
|
# darker are inverse operations, the results of a series of invocations of
|
334
330
|
# these two methods might be inconsistent because of rounding errors.
|
335
331
|
def lighter(k=1)
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
332
|
+
k = 0.7**k
|
333
|
+
i = 30
|
334
|
+
r=self.r
|
335
|
+
g=self.g
|
336
|
+
b=self.b
|
337
|
+
return Rubyvis.rgb(i, i, i, a) if (!r and !g and !b)
|
338
|
+
r = i if (r and (r < i))
|
339
|
+
g = i if (g and (g < i))
|
340
|
+
b = i if (b and (b < i))
|
341
|
+
Rubyvis.rgb(
|
342
|
+
[255, (r/k).floor].min,
|
343
|
+
[255, (g/k).floor].min,
|
344
|
+
[255, (b/k).floor].min,
|
345
|
+
a)
|
350
346
|
end
|
351
347
|
# Returns a new color that is a darker version of this color. This method
|
352
348
|
# applies an arbitrary scale factor to each of the three RGB components of this
|
@@ -368,7 +364,6 @@ module Rubyvis
|
|
368
364
|
end
|
369
365
|
# Represents a color in HSL space.
|
370
366
|
class Hsl < Color
|
371
|
-
|
372
367
|
# The hue, an integer in [0, 360].
|
373
368
|
attr_accessor :h
|
374
369
|
# The saturation, a float in [0, 1].
|
@@ -386,6 +381,9 @@ module Rubyvis
|
|
386
381
|
@l=l
|
387
382
|
@a=a
|
388
383
|
end
|
384
|
+
def ==(v)
|
385
|
+
self.class==v.class and @h==v.h and @s==v.s and @l==v.l and @a==v.a
|
386
|
+
end
|
389
387
|
|
390
388
|
# Returns the RGB color equivalent to this HSL color.
|
391
389
|
def rgb
|
@@ -416,7 +414,7 @@ module Rubyvis
|
|
416
414
|
return m1
|
417
415
|
}
|
418
416
|
vv=lambda {|h1|
|
419
|
-
(v(h1) * 255).round
|
417
|
+
(v.call(h1) * 255).round
|
420
418
|
}
|
421
419
|
|
422
420
|
Rubyvis.rgb(vv.call(h + 120), vv.call(h), vv.call(h - 120), a)
|
data/lib/rubyvis/layout.rb
CHANGED
@@ -23,7 +23,7 @@ module Rubyvis
|
|
23
23
|
end
|
24
24
|
@properties[name]=true
|
25
25
|
self.property_method(name,false, func, self)
|
26
|
-
define_method(name.to_s+"=") {|v|
|
26
|
+
define_method(name.to_s + "=") {|v|
|
27
27
|
self.send(name,v)
|
28
28
|
}
|
29
29
|
end
|
@@ -32,6 +32,7 @@ module Rubyvis
|
|
32
32
|
end
|
33
33
|
|
34
34
|
require 'rubyvis/layout/stack'
|
35
|
+
require 'rubyvis/layout/horizon'
|
35
36
|
require 'rubyvis/layout/grid'
|
36
37
|
require 'rubyvis/layout/network'
|
37
38
|
require 'rubyvis/layout/hierarchy'
|
@@ -41,5 +42,5 @@ require 'rubyvis/layout/partition'
|
|
41
42
|
require 'rubyvis/layout/cluster'
|
42
43
|
require 'rubyvis/layout/indent'
|
43
44
|
require 'rubyvis/layout/pack'
|
44
|
-
|
45
|
+
require 'rubyvis/layout/arc'
|
45
46
|
|
@@ -0,0 +1,188 @@
|
|
1
|
+
module Rubyvis
|
2
|
+
class Layout
|
3
|
+
# Alias for Rubyvis::Layout::Arc
|
4
|
+
def self.Arc
|
5
|
+
Rubyvis::Layout::Arc
|
6
|
+
end
|
7
|
+
|
8
|
+
# @class Implements a layout for arc diagrams. An arc diagram is a network
|
9
|
+
# visualization with a one-dimensional layout of nodes, using circular arcs to
|
10
|
+
# render links between nodes. For undirected networks, arcs are rendering on a
|
11
|
+
# single side; this makes arc diagrams useful as annotations to other
|
12
|
+
# two-dimensional network layouts, such as rollup, matrix or table layouts. For
|
13
|
+
# directed networks, links in opposite directions can be rendered on opposite
|
14
|
+
# sides using <tt>directed(true)</tt>.
|
15
|
+
#
|
16
|
+
# <p>Arc layouts are particularly sensitive to node ordering; for best results,
|
17
|
+
# order the nodes such that related nodes are close to each other. A poor
|
18
|
+
# (e.g., random) order may result in large arcs with crossovers that impede
|
19
|
+
# visual processing. A future improvement to this layout may include automatic
|
20
|
+
# reordering using, e.g., spectral graph layout or simulated annealing.
|
21
|
+
#
|
22
|
+
# <p>This visualization technique is related to that developed by
|
23
|
+
# M. Wattenberg, <a
|
24
|
+
# href="http://www.research.ibm.com/visual/papers/arc-diagrams.pdf">"Arc
|
25
|
+
# Diagrams: Visualizing Structure in Strings"</a> in <i>IEEE InfoVis</i>, 2002.
|
26
|
+
# However, this implementation is limited to simple node-link networks, as
|
27
|
+
# opposed to structures with hierarchical self-similarity (such as strings).
|
28
|
+
#
|
29
|
+
# <p>As with other network layouts, three mark prototypes are provided:<ul>
|
30
|
+
#
|
31
|
+
# <li><tt>node</tt> - for rendering nodes; typically a {@link pv.Dot}.
|
32
|
+
# <li><tt>link</tt> - for rendering links; typically a {@link pv.Line}.
|
33
|
+
# <li><tt>label</tt> - for rendering node labels; typically a {@link pv.Label}.
|
34
|
+
#
|
35
|
+
# </ul>For more details on how this layout is structured and can be customized,
|
36
|
+
# see {@link pv.Layout.Network}.
|
37
|
+
|
38
|
+
class Arc < Network
|
39
|
+
@properties=Network.properties.dup
|
40
|
+
attr_accessor :_interpolate, :_directed, :_reverse
|
41
|
+
def initialize
|
42
|
+
super
|
43
|
+
@_interpolate=nil # cached interpolate
|
44
|
+
@_directed=nil # cached directed
|
45
|
+
@_reverse=nil # cached reverse
|
46
|
+
@_sort=nil
|
47
|
+
that=self
|
48
|
+
@link.data(lambda {|_p|
|
49
|
+
s=_p.source_node;t=_p.target_node
|
50
|
+
that._reverse != (that._directed or (s.breadth < t.breadth)) ? [s, t] : [t, s]
|
51
|
+
}).interpolate(lambda{ that._interpolate})
|
52
|
+
end
|
53
|
+
|
54
|
+
def build_implied(s)
|
55
|
+
return true if network_build_implied(s)
|
56
|
+
# Cached
|
57
|
+
|
58
|
+
nodes = s.nodes
|
59
|
+
orient = s.orient
|
60
|
+
sort = @_sort
|
61
|
+
index = Rubyvis.range(nodes.size)
|
62
|
+
w = s.width
|
63
|
+
h = s.height
|
64
|
+
r = [w,h].min / 2.0
|
65
|
+
# /* Sort the nodes. */
|
66
|
+
if (sort)
|
67
|
+
index.sort! {|a,b| sort.call(nodes[a],nodes[b])}
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
|
72
|
+
#/** @private Returns the mid-angle, given the breadth. */
|
73
|
+
mid_angle=lambda do |b|
|
74
|
+
case orient
|
75
|
+
when "top"
|
76
|
+
-Math::PI / 2.0
|
77
|
+
when "bottom"
|
78
|
+
Math::PI / 2.0
|
79
|
+
when "left"
|
80
|
+
Math::PI
|
81
|
+
when "right"
|
82
|
+
0
|
83
|
+
when "radial"
|
84
|
+
(b - 0.25) * 2.0 * Math::PI
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# /** @private Returns the x-position, given the breadth. */
|
89
|
+
x= lambda do |b|
|
90
|
+
case orient
|
91
|
+
when "top"
|
92
|
+
b * w
|
93
|
+
when "bottom"
|
94
|
+
b * w
|
95
|
+
when "left"
|
96
|
+
0;
|
97
|
+
when "right"
|
98
|
+
w;
|
99
|
+
when "radial"
|
100
|
+
w / 2.0 + r * Math.cos(mid_angle.call(b))
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# /** @private Returns the y-position, given the breadth. */
|
105
|
+
y=lambda do |b|
|
106
|
+
case orient
|
107
|
+
when "top"
|
108
|
+
0;
|
109
|
+
when "bottom"
|
110
|
+
h;
|
111
|
+
when "left"
|
112
|
+
b* h
|
113
|
+
when "right"
|
114
|
+
b * h
|
115
|
+
when "radial"
|
116
|
+
h / 2.0 + r * Math.sin(mid_angle.call(b))
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
#/* Populate the x, y and mid-angle attributes. */
|
121
|
+
nodes.each_with_index do |nod, i|
|
122
|
+
n=nodes[index[i]]
|
123
|
+
n.breadth=(i+0.5) / nodes.size
|
124
|
+
b=n.breadth
|
125
|
+
n.x=x[b]
|
126
|
+
n.y=y[b]
|
127
|
+
n.mid_angle=mid_angle[b]
|
128
|
+
end
|
129
|
+
|
130
|
+
@_directed = s.directed
|
131
|
+
@_interpolate = s.orient == "radial" ? "linear" : "polar"
|
132
|
+
@_reverse = s.orient == "right" or s.orient == "top"
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
##
|
137
|
+
# :attr: orient
|
138
|
+
# The orientation. The default orientation is "left", which means that nodes
|
139
|
+
# will be positioned from left-to-right in the order they are specified in the
|
140
|
+
# <tt>nodes</tt> property. The following orientations are supported:<ul>
|
141
|
+
#
|
142
|
+
# <li>left - left-to-right.
|
143
|
+
# <li>right - right-to-left.
|
144
|
+
# <li>top - top-to-bottom.
|
145
|
+
# <li>bottom - bottom-to-top.
|
146
|
+
# <li>radial - radially, starting at 12 o'clock and proceeding clockwise.</ul>
|
147
|
+
|
148
|
+
##
|
149
|
+
# :attr: directed
|
150
|
+
# Whether this arc digram is directed (bidirectional); only applies to
|
151
|
+
# non-radial orientations. By default, arc digrams are undirected, such that
|
152
|
+
# all arcs appear on one side. If the arc digram is directed, then forward
|
153
|
+
# links are drawn on the conventional side (the same as as undirected
|
154
|
+
# links--right, left, bottom and top for left, right, top and bottom,
|
155
|
+
# respectively), while reverse links are drawn on the opposite side.
|
156
|
+
|
157
|
+
attr_accessor_dsl :orient, :directed
|
158
|
+
|
159
|
+
def self.defaults
|
160
|
+
Arc.new.mark_extend(Network.defaults).
|
161
|
+
orient("bottom")
|
162
|
+
end
|
163
|
+
|
164
|
+
# Specifies an optional sort function. The sort function follows the same
|
165
|
+
# comparator contract required by {@link pv.Dom.Node#sort}. Specifying a sort
|
166
|
+
# function provides an alternative to sort the nodes as they are specified by
|
167
|
+
# the <tt>nodes</tt> property; the main advantage of doing this is that the
|
168
|
+
# comparator function can access implicit fields populated by the network
|
169
|
+
# layout, such as the <tt>linkDegree</tt>.
|
170
|
+
#
|
171
|
+
# <p>Note that arc diagrams are particularly sensitive to order. This is
|
172
|
+
# referred to as the seriation problem, and many different techniques exist to
|
173
|
+
# find good node orders that emphasize clusters, such as spectral layout and
|
174
|
+
# simulated annealing.
|
175
|
+
#
|
176
|
+
# @param {function} f comparator function for nodes.
|
177
|
+
# @returns {pv.Layout.Arc} this.
|
178
|
+
def sort(f=nil,&block)
|
179
|
+
f||=block
|
180
|
+
@_sort=f
|
181
|
+
self
|
182
|
+
end
|
183
|
+
|
184
|
+
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
@@ -0,0 +1,153 @@
|
|
1
|
+
module Rubyvis
|
2
|
+
class Layout
|
3
|
+
# Alias for Rubyvis::Layout::Horizon
|
4
|
+
def self.Horizon
|
5
|
+
Rubyvis::Layout::Horizon
|
6
|
+
end
|
7
|
+
|
8
|
+
# Implements a horizon layout, which is a variation of a single-series
|
9
|
+
# area chart where the area is folded into multiple bands. Color is used to
|
10
|
+
# encode band, allowing the size of the chart to be reduced significantly
|
11
|
+
# without impeding readability. This layout algorithm is based on the work of
|
12
|
+
# J. Heer, N. Kong and M. Agrawala in <a href="http://hci.stanford.edu/publications/2009/heer-horizon-chi09.pdf">"Sizing
|
13
|
+
# the Horizon: The Effects of Chart Size and Layering on the Graphical
|
14
|
+
# Perception of Time Series Visualizations"</a>, CHI 2009.
|
15
|
+
#
|
16
|
+
# <p>This layout exports a single <tt>band</tt> mark prototype, which is
|
17
|
+
# intended to be used with an area mark. The band mark is contained in a panel
|
18
|
+
# which is replicated per band (and for negative/positive bands). For example,
|
19
|
+
# to create a simple horizon graph given an array of numbers:
|
20
|
+
#
|
21
|
+
# vis.add(Rubyvis::Layout::Horizon)
|
22
|
+
# .bands(n)
|
23
|
+
# .band.add(Rubyvis::Area)
|
24
|
+
# .data(data)
|
25
|
+
# .left(lambda { index * 35})
|
26
|
+
# .height(lambda {|d| d * 40})
|
27
|
+
#
|
28
|
+
# The layout can be further customized by changing the number of bands, and
|
29
|
+
# toggling whether the negative bands are mirrored or offset. (See the
|
30
|
+
# above-referenced paper for guidance.)
|
31
|
+
#
|
32
|
+
# <p>The <tt>fill_style</tt> of the area can be overridden, though typically it
|
33
|
+
# is easier to customize the layout's behavior through the custom
|
34
|
+
# <tt>background_style</tt>, <tt>positive_style</tt> and <tt>negative_style</tt>
|
35
|
+
# properties. By default, the background is white, positive bands are blue, and
|
36
|
+
# negative bands are red. For the most accurate presentation, use fully-opaque
|
37
|
+
# colors of equal intensity for the negative and positive bands.
|
38
|
+
class Horizon < Layout
|
39
|
+
@properties=Layout.properties.dup
|
40
|
+
# The band prototype. This prototype is intended to be used with an Area
|
41
|
+
# mark to render the horizon bands.
|
42
|
+
attr_accessor :band
|
43
|
+
attr_accessor :_bands, :_mode, :_size, :_fill, :_red, :_blue
|
44
|
+
def initialize
|
45
|
+
super
|
46
|
+
@_bands=nil
|
47
|
+
@_mode=nil # cached mode
|
48
|
+
@_size=nil # cached height
|
49
|
+
@_fill=nil # cached background style
|
50
|
+
@_red=nil # cached negative color (ramp)
|
51
|
+
@_blue=nil # cached positive color (ramp)
|
52
|
+
@_bands_panel=_bands_panel
|
53
|
+
@band=_band
|
54
|
+
end
|
55
|
+
def build_implied(s)
|
56
|
+
layout_build_implied(s)
|
57
|
+
@_bands=s.bands
|
58
|
+
@_mode=s.mode
|
59
|
+
@_size=((@_mode == "color" ? 0.5 : 1) * s.height).round
|
60
|
+
@_fill=s.background_style
|
61
|
+
@_red=Rubyvis.ramp(@_fill, s.negative_style).domain(0,@_bands)
|
62
|
+
@_blue=Rubyvis.ramp(@_fill, s.positive_style).domain(0,@_bands)
|
63
|
+
|
64
|
+
end
|
65
|
+
def _bands_panel
|
66
|
+
that=self
|
67
|
+
Rubyvis::Panel.new().
|
68
|
+
data(lambda {Rubyvis.range(that._bands.to_f * 2)}).
|
69
|
+
overflow("hidden").
|
70
|
+
height(lambda {that._size}).
|
71
|
+
top(lambda {|i| that._mode=='color' ? (i & 1) * that._size : 0 }).
|
72
|
+
fill_style(lambda {|i| i!=0 ? nil : that._fill})
|
73
|
+
end
|
74
|
+
|
75
|
+
def _band
|
76
|
+
that=self
|
77
|
+
m=Rubyvis::Mark.new().
|
78
|
+
top(lambda {|d,i|
|
79
|
+
(that._mode == "mirror" and (i & 1)!=0) ? (i + 1 >> 1) * that._size : nil
|
80
|
+
}).
|
81
|
+
bottom(lambda {|d,i|
|
82
|
+
crit= (i & 1)!= 0 ? i & 1 : -1
|
83
|
+
(that._mode == "mirror") ? ((i & 1)!=0 ? nil : (i + 1 >> 1) * -that._size) : (crit * (i + 1 >> 1) * that._size)
|
84
|
+
}).
|
85
|
+
fill_style(lambda {|d,i|
|
86
|
+
((i & 1)!=0 ? that._red : that._blue).scale((i >> 1) + 1)
|
87
|
+
})
|
88
|
+
|
89
|
+
class << m # :nodoc:
|
90
|
+
def that_and_bands(that,bands)
|
91
|
+
@that = that
|
92
|
+
@bands=bands
|
93
|
+
end
|
94
|
+
def add(type)
|
95
|
+
bands=@bands
|
96
|
+
that = @that
|
97
|
+
that.add( Rubyvis.Panel ).mark_extend(bands). add(type). mark_extend(self)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
m.that_and_bands(self, @_bands_panel)
|
102
|
+
m
|
103
|
+
end
|
104
|
+
|
105
|
+
##
|
106
|
+
# :attr: mode
|
107
|
+
# The horizon mode: offset, mirror, or color. The default is "offset".
|
108
|
+
|
109
|
+
##
|
110
|
+
# :attr: bands
|
111
|
+
# The number of bands. Must be at least one. The default value is two.
|
112
|
+
#
|
113
|
+
|
114
|
+
##
|
115
|
+
# :attr: positive_style
|
116
|
+
# The positive band color; if non-null, the interior of positive bands are
|
117
|
+
# filled with the specified color. The default value of this property is blue.
|
118
|
+
# For accurate blending, this color should be fully opaque.
|
119
|
+
#
|
120
|
+
|
121
|
+
##
|
122
|
+
# :attr: negative_style
|
123
|
+
# The negative band color; if non-null, the interior of negative bands are
|
124
|
+
# filled with the specified color. The default value of this property is red.
|
125
|
+
# For accurate blending, this color should be fully opaque.
|
126
|
+
#
|
127
|
+
|
128
|
+
##
|
129
|
+
# :attr: background_style
|
130
|
+
# The background color. The panel background is filled with the specified
|
131
|
+
# color, and the negative and positive bands are filled with an interpolated
|
132
|
+
# color between this color and the respective band color. The default value of
|
133
|
+
# this property is white. For accurate blending, this color should be fully
|
134
|
+
# opaque.
|
135
|
+
#
|
136
|
+
|
137
|
+
attr_accessor_dsl :bands, :mode, :background_style, [:background_style, lambda {|d| Rubyvis.color(d)}], [:positive_style, lambda {|d| Rubyvis.color(d)}], [:negative_style, lambda {|d| Rubyvis.color(d)}]
|
138
|
+
|
139
|
+
# Default properties for horizon layouts. By default, there are two bands, the
|
140
|
+
# mode is "offset", the background style is "white", the positive style is
|
141
|
+
# blue, negative style is red.
|
142
|
+
def self.defaults
|
143
|
+
Horizon.new.mark_extend(Layout.defaults).
|
144
|
+
bands(2).
|
145
|
+
mode('offset').
|
146
|
+
background_style('white').
|
147
|
+
positive_style('#1f77b4').
|
148
|
+
negative_style('#d62728')
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|