Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 70 additions & 10 deletions source/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ Bluff.Base = new JS.Class({
DATA_LABEL_INDEX: 0,
DATA_VALUES_INDEX: 1,
DATA_COLOR_INDEX: 2,
DATA_DASH_STYLE_INDEX: 3,

// Space around text elements. Mostly used for vertical spacing
LEGEND_MARGIN: 20,
Expand Down Expand Up @@ -138,7 +139,10 @@ Bluff.Base = new JS.Class({

// Get or set the list of colors that will be used to draw the bars or lines.
colors: null,


// Get or set the list of dash styles that will be used to draw lines.
dash_styles : null,

// The large title of the graph displayed at the top
title: null,

Expand All @@ -152,6 +156,9 @@ Bluff.Base = new JS.Class({

// Prevent drawing of the legend
hide_legend: null,

// Draws lines in legend instead of boxes (e.g. when dashing is used)
line_legend: null,

// Prevent drawing of the title
hide_title: null,
Expand Down Expand Up @@ -328,14 +335,48 @@ Bluff.Base = new JS.Class({
this.colors = color_list || [];
this._color_index = 0;
},

// Add a dash style to the list of available dash styles for lines.
// A dash style is specified by an array like [x, y, z, ...] meaning
// Draw x pixels, then leave y pixels free, then draw z pixels etc.
// It repeats from the beginning if the line is longer than the sum of the length
// of the specified dashes
//
// Example:
// add_dash_style([3, 1])
add_dash_style: function(dash_style) {
this.dash_styles.push(dash_style);
},

// Replace the entire dash style list with a new array of dash styles. Also
// aliased as the dash_styles= setter method.
//
// If you specify fewer colors than the number of datasets you intend
// to draw, 'increment_dash_style' will cycle through the array, reusing
// dash styles as needed.
//
// Note that (as with the 'set_theme' method), you should set up the dash style
// list before you send your data (via the 'data' method). Calls to the
// 'data' method made prior to this call will use whatever dash style scheme
// was in place at the time data was called.
//
// Example:
// replace_dash_styles [[9999], [10, 5], [6, 3, 20, 10]]
// The [9999] style means a solid line, since most drawn lines will be most likely
// shorter than 9999 pixels
replace_dash_styles: function(dash_style_list) {
this.dash_styles = dash_style_list || [];
this._dash_style_index = 0;
},

// You can set a theme manually. Assign a hash to this method before you
// send your data.
//
// graph.set_theme({
// colors: ['orange', 'purple', 'green', 'white', 'red'],
// marker_color: 'blue',
// background_colors: ['black', 'grey']
// background_colors: ['black', 'grey'],
// dash_styles: [[9999], [10,5]]
// })
//
// background_image: 'squirrel.png' is also possible.
Expand All @@ -351,11 +392,13 @@ Bluff.Base = new JS.Class({
marker_color: 'white',
font_color: 'black',
background_colors: null,
background_image: null
background_image: null,
dash_styles : [[9999]]
};
for (var key in options) this._theme_options[key] = options[key];

this.colors = this._theme_options.colors;
this.dash_styles = this._theme_options.dash_styles;
this.marker_color = this._theme_options.marker_color;
this.font_color = this._theme_options.font_color || this.marker_color;
this._additional_line_colors = this._theme_options.additional_line_colors;
Expand Down Expand Up @@ -501,19 +544,20 @@ Bluff.Base = new JS.Class({
// graph.
//
// If the color argument is nil, the next color from the default theme will
// be used.
// be used, same counts for the dash_style argument.
//
// NOTE: If you want to use a preset theme, you must set it before calling
// data().
//
// Example:
// data("Bart S.", [95, 45, 78, 89, 88, 76], '#ffcc00')
data: function(name, data_points, color) {
// data("Bart S.", [95, 45, 78, 89, 88, 76], '#ffcc00', [9999])
data: function(name, data_points, color, dash_style) {
data_points = (data_points === undefined) ? [] : data_points;
color = color || null;

dash_style = dash_style || null;

data_points = Bluff.array(data_points); // make sure it's an array
this._data.push([name, data_points, (color || this._increment_color())]);
this._data.push([name, data_points, (color || this._increment_color()), (dash_style || this._increment_dash_style())]);
// Set column count if this is larger than previous counts
this._column_count = (data_points.length > this._column_count) ? data_points.length : this._column_count;

Expand Down Expand Up @@ -603,7 +647,7 @@ Bluff.Base = new JS.Class({
else
norm_data_points.push((data_point - this.minimum_value) / this._spread);
}, this);
this._norm_data.push([data_row[this.klass.DATA_LABEL_INDEX], norm_data_points, data_row[this.klass.DATA_COLOR_INDEX]]);
this._norm_data.push([data_row[this.klass.DATA_LABEL_INDEX], norm_data_points, data_row[this.klass.DATA_COLOR_INDEX], data_row[this.klass.DATA_DASH_STYLE_INDEX]]);
}, this);
}
},
Expand Down Expand Up @@ -832,10 +876,19 @@ Bluff.Base = new JS.Class({
// Now draw box with color of this dataset
this._d.stroke = 'transparent';
this._d.fill = this._data[index][this.klass.DATA_COLOR_INDEX];
this._d.rectangle(current_x_offset,
if (this.line_legend) {
this._d.stroke = this._data[index][this.klass.DATA_COLOR_INDEX];
this._d.dashed_line(current_x_offset,
current_y_offset - legend_square_width / 2.0,
current_x_offset + legend_square_width,
current_y_offset + legend_square_width / 2.0,
this._data[index][this.klass.DATA_DASH_STYLE_INDEX]);
} else {
this._d.rectangle(current_x_offset,
current_y_offset - legend_square_width / 2.0,
current_x_offset + legend_square_width,
current_y_offset + legend_square_width / 2.0);
}

this._d.pointsize = this.legend_font_size;
var metrics = this._d.get_type_metrics(legend_label);
Expand Down Expand Up @@ -1074,6 +1127,13 @@ Bluff.Base = new JS.Class({
this._color_index = (this._color_index + 1) % this.colors.length;
return this.colors[offset];
},

// Returns the next dash style in your dash style list.
_increment_dash_style: function() {
var offset = this._dash_style_index;
this._dash_style_index = (this._dash_style_index + 1) % this.dash_styles.length;
return this.dash_styles[offset];
},

// Return a formatted string representing a number value that should be
// printed as a label.
Expand Down
2 changes: 1 addition & 1 deletion source/line.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ Bluff.Line = new JS.Class(Bluff.Base, {
this._clip_value_if_greater_than(this._columns / (this._norm_data[0][this.klass.DATA_VALUES_INDEX].length * 2), 7.0);

if (!this.hide_lines && prev_x !== null && prev_y !== null) {
this._d.line(prev_x, prev_y, new_x, new_y);
this._d.dashed_line(prev_x, prev_y, new_x, new_y, data_row[this.klass.DATA_DASH_STYLE_INDEX]);
} else if (this._one_point) {
// Show a circle if there's just one point
this._d.circle(new_x, new_y, new_x - circle_radius, new_y);
Expand Down
32 changes: 32 additions & 0 deletions source/renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,38 @@ Bluff.Renderer = new JS.Class({
this._ctx.lineTo(this._sx * ex, this._sy * ey);
this._ctx.stroke();
},

dashed_line: function(sx, sy, ex, ey, dashstyle) {
if (!dashstyle) {
dashstyle = [20, 10];
}
var count = dashstyle.length;
this._ctx.strokeStyle = this.stroke;
this._ctx.lineWidth = this.stroke_width;
this._ctx.beginPath();
this._ctx.moveTo(this._sx * sx, this._sy * sy);
var dx = (ex - sx), dy = (ey - sy);
var slope = dy / dx;
var rdist = Math.sqrt(dx * dx + dy * dy);
var index = 0, draw = true;
while (rdist >= 0.1) {
var length = dashstyle[index++ % count];
if (length > rdist) {
length = rdist;
}
var step = Math.sqrt(length * length / (1+slope * slope));
sx += step;
sy += slope * step;
if (draw) {
this._ctx.lineTo(this._sx * sx, this._sy * sy);
this._ctx.stroke();
} else {
this._ctx.moveTo(this._sx * sx, this._sy * sy);
}
rdist -= length;
draw = !draw;
}
},

polyline: function(points) {
this._ctx.fillStyle = this.fill;
Expand Down