ol-ext-datatable
Version:
Datatables version
288 lines (258 loc) • 8.25 kB
JavaScript
/* Copyright (c) 2015 Jean-Marc VIGLINO,
released under the CeCILL-B license (French BSD license)
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
*
* Add a chart style to display charts (pies or bars) on a map
*/
import ol from 'ol'
import ol_style_RegularShape from 'ol/style/regularshape'
import ol_style_Fill from 'ol/style/fill'
import ol_color from 'ol/color'
/**
* @requires ol.style.Circle
* @requires ol.structs.IHasChecksum
*/
/**
* @classdesc
* Set chart style for vector features.
*
* @constructor
* @param {} options
* @param {String} options.type Chart type: pie,pie3D, donut or bar
* @param {number} options.radius Chart radius/size, default 20
* @param {number} options.rotation Rotation in radians (positive rotation clockwise). Default is 0.
* @param {bool} options.snapToPixel use integral numbers of pixels, default true
* @param {_ol_style_Stroke_} options.stroke stroke style
* @param {String|Array<ol_color>} options.colors predefined color set "classic","dark","pale","pastel","neon" / array of color string, default classic
* @param {number} options.offsetX X offset in px
* @param {number} options.offsetY Y offset in px
* @param {number} options.animation step in an animation sequence [0,1]
* @see [Statistic charts example](../../examples/map.style.chart.html)
* @extends {ol_style_RegularShape}
* @implements {ol.structs.IHasChecksum}
* @api
*/
var ol_style_Chart = function(opt_options)
{ options = opt_options || {};
var strokeWidth = 0;
if (opt_options.stroke) strokeWidth = opt_options.stroke.getWidth();
ol_style_RegularShape.call (this,
{ radius: options.radius + strokeWidth,
fill: new ol_style_Fill({color: [0,0,0]}),
rotation: options.rotation,
snapToPixel: options.snapToPixel
});
if (options.scale) this.setScale(options.scale);
this.stroke_ = options.stroke;
this.radius_ = options.radius || 20;
this.donutratio_ = options.donutRatio || 0.5;
this.type_ = options.type;
this.offset_ = [options.offsetX ? options.offsetX : 0, options.offsetY ? options.offsetY : 0];
this.animation_ = (typeof(options.animation) == 'number') ? { animate:true, step:options.animation } : this.animation_ = { animate:false, step:1 };
this.data_ = options.data;
if (options.colors instanceof Array)
{ this.colors_ = options.colors;
}
else
{ this.colors_ = ol_style_Chart.colors[options.colors];
if(!this.colors_) this.colors_ = ol_style_Chart.colors.classic;
}
this.renderChart_();
};
ol.inherits(ol_style_Chart, ol_style_RegularShape);
/** Default color set: classic, dark, pale, pastel, neon
*/
ol_style_Chart.colors =
{ "classic": ["#ffa500","blue","red","green","cyan","magenta","yellow","#0f0"],
"dark": ["#960","#003","#900","#060","#099","#909","#990","#090"],
"pale": ["#fd0","#369","#f64","#3b7","#880","#b5d","#666"],
"pastel": ["#fb4","#79c","#f66","#7d7","#acc","#fdd","#ff9","#b9b"],
"neon": ["#ff0","#0ff","#0f0","#f0f","#f00","#00f"]
}
/**
* Clones the style.
* @return {ol_style_Chart}
*/
ol_style_Chart.prototype.clone = function()
{ var s = new ol_style_Chart(
{ type: this.type_,
radius: this.radius_,
rotation: this.getRotation(),
scale: this.getScale(),
data: this.getData(),
snapToPixel: this.getSnapToPixel(),
stroke: this.stroke_,
colors: this.colors_,
offsetX: this.offset_[0],
offsetY: this.offset_[1],
animation: this.animation_
});
s.setScale(this.getScale());
s.setOpacity(this.getOpacity());
return s;
};
/** Get data associatied with the chart
*/
ol_style_Chart.prototype.getData = function()
{ return this.data_;
}
/** Set data associatied with the chart
* @param {Array<number>}
*/
ol_style_Chart.prototype.setData = function(data)
{ this.data_ = data;
this.renderChart_();
}
/** Get symbol radius
*/
ol_style_Chart.prototype.getRadius = function()
{ return this.radius_;
}
/** Set symbol radius
* @param {number} symbol radius
* @param {number} donut ratio
*/
ol_style_Chart.prototype.setRadius = function(radius, ratio)
{ this.radius_ = radius;
this.donuratio_ = ratio || this.donuratio_;
this.renderChart_();
}
/** Set animation step
* @param {false|number} false to stop animation or the step of the animation [0,1]
*/
ol_style_Chart.prototype.setAnimation = function(step)
{ if (step===false)
{ if (this.animation_.animate == false) return;
this.animation_.animate = false;
}
else
{ if (this.animation_.step == step) return;
this.animation_.animate = true;
this.animation_.step = step;
}
this.renderChart_();
}
/** @private
*/
ol_style_Chart.prototype.renderChart_ = function(atlasManager)
{ var strokeStyle;
var strokeWidth = 0;
if (this.stroke_)
{ strokeStyle = ol_color.asString(this.stroke_.getColor());
strokeWidth = this.stroke_.getWidth();
}
// no atlas manager is used, create a new canvas
var canvas = this.getImage();
// draw the circle on the canvas
var context = (canvas.getContext('2d'));
context.clearRect(0, 0, canvas.width, canvas.height);
context.lineJoin = 'round';
var sum=0;
for (var i=0; i<this.data_.length; i++)
sum += this.data_[i];
// reset transform
context.setTransform(1, 0, 0, 1, 0, 0);
// then move to (x, y)
context.translate(0,0);
var step = this.animation_.animate ? this.animation_.step : 1;
//console.log(this.animation_.step)
// Draw pie
switch (this.type_)
{ case "donut":
case "pie3D":
case "pie":
{ var a, a0 = Math.PI * (step-1.5);
var c = canvas.width/2;
context.strokeStyle = strokeStyle;
context.lineWidth = strokeWidth;
context.save();
if (this.type_=="pie3D")
{ context.translate(0, c*0.3);
context.scale(1, 0.7);
context.beginPath();
context.fillStyle = "#369";
context.arc ( c, c*1.4, this.radius_ *step, 0, 2*Math.PI);
context.fill();
context.stroke();
}
if (this.type_=="donut")
{ context.save();
context.beginPath();
context.rect ( 0,0,2*c,2*c );
context.arc ( c, c, this.radius_ *step *this.donutratio_, 0, 2*Math.PI);
context.clip("evenodd");
}
for (var i=0; i<this.data_.length; i++)
{ context.beginPath();
context.moveTo(c,c);
context.fillStyle = this.colors_[i%this.colors_.length];
a = a0 + 2*Math.PI*this.data_[i]/sum *step;
context.arc ( c, c, this.radius_ *step, a0, a);
context.closePath();
context.fill();
context.stroke();
a0 = a;
}
if (this.type_=="donut")
{ context.restore();
context.beginPath();
context.strokeStyle = strokeStyle;
context.lineWidth = strokeWidth;
context.arc ( c, c, this.radius_ *step *this.donutratio_, Math.PI * (step-1.5), a0);
context.stroke();
}
context.restore();
break;
}
case "bar":
default:
{ var max=0;
for (var i=0; i<this.data_.length; i++)
{ if (max < this.data_[i]) max = this.data_[i];
}
var s = Math.min(5,2*this.radius_/this.data_.length);
var c = canvas.width/2;
var b = canvas.width - strokeWidth;
var x, x0 = c - this.data_.length*s/2
context.strokeStyle = strokeStyle;
context.lineWidth = strokeWidth;
for (var i=0; i<this.data_.length; i++)
{ context.beginPath();
context.fillStyle = this.colors_[i%this.colors_.length];
x = x0 + s;
var h = this.data_[i]/max*2*this.radius_ *step;
context.rect ( x0, b-h, s, h);
//console.log ( x0+", "+(b-this.data_[i]/max*2*this.radius_)+", "+x+", "+b);
context.closePath();
context.fill();
context.stroke();
x0 = x;
}
}
}
// Set Anchor
var a = this.getAnchor();
a[0] = c - this.offset_[0];
a[1] = c - this.offset_[1];
};
/**
* @inheritDoc
*/
ol_style_Chart.prototype.getChecksum = function()
{
var strokeChecksum = (this.stroke_!==null) ?
this.stroke_.getChecksum() : '-';
var recalculate = (this.checksums_===null) ||
(strokeChecksum != this.checksums_[1] ||
fillChecksum != this.checksums_[2] ||
this.radius_ != this.checksums_[3] ||
this.data_.join('|') != this.checksums_[4]);
if (recalculate) {
var checksum = 'c' + strokeChecksum + fillChecksum
+ ((this.radius_ !== void 0) ? this.radius_.toString() : '-')
+ this.data_.join('|');
this.checksums_ = [checksum, strokeChecksum, fillChecksum, this.radius_, this.data_.join('|')];
}
return this.checksums_[0];
};
export default ol_style_Chart