Files
d3-progress-meter/d3-progress-meter.html
2016-02-19 14:53:05 +01:00

226 lines
5.3 KiB
HTML

<!doctype html>
<link rel="import" href="../polymer/polymer.html">
<script src="../d3/d3.min.js"></script>
<!--
An animated chart that shows the progress as a meter
### Example
```html
<d3-progress-meter radius="100" percentage="0.35" current-text="70" goal-text="Goal: 200" type-text="transactions"></d3-progress-meter>
```
@demo demo/index.html
-->
<dom-module id="d3-progress-meter">
<template>
<style>
:host {
display: inline-block;
}
#current,#goal,#type,#caption {
font-family: Arial, sans-serif;
}
#current {
font-weight: bold;
}
#type {
margin-top: 5px;
text-align: center;
text-transform: uppercase;
white-space: nowrap;
overflow-x: hidden;
text-overflow: ellipsis;
}
#caption {
/*var(--secondary-text-color)*/
color: #737373;
text-align: center;
}
</style>
<svg width$=[[_diameter]] height$=[[_diameter]]>
<g transform$=[[_transform]]>
<g>
<path id="background"></path>
<path id="progress" class$=[[_progressLevel]]></path>
<text id="current" dy="-.2em" text-anchor="middle">[[currentText]]</text>
<text id="goal" dy="1.5em" text-anchor="middle">[[goalText]]</text>
</g>
</g>
</svg>
<div id="type">[[typeText]]</div>
<div hidden=[[!caption]] id="caption">[[caption]]</div>
</template>
</dom-module>
<script>
(function() {
Polymer({
is: 'd3-progress-meter',
properties: {
/**
* Radius of the meter. The element will have twice the size of the radius
*/
radius: {
type: Number,
value: 100,
observer: '_radiusChanged'
},
/**
* Progress in percent
*/
percentage: {
type: Number,
observer: '_percentageChanged'
},
/**
* Large number showing current progress
*/
currentText: String,
/**
* Small text indicating when progress will be 100%
*/
goalText: String,
/**
* Bottom text describing for what progress is measured
*/
typeText: String,
/**
* Optional secondary text displayed under the type text
*/
caption: String,
/**
* Color of the background circle
*/
backgroundColor: String,
/**
* Array of three colors that specify, in order: low progress, medium progress, high progress
*/
progressColors: [],
/**
* Amount of progress made (absolute number)
*/
_progress: {
type: Number,
value: 0
},
_diameter: {
type: Number,
computed: '_computeDiameter(radius)'
},
_transform: {
type: String,
computed: '_computeTransform(radius)'
},
_progressLevel: {
type: Number,
computed: '_computeProgressLevel(percentage)'
}
},
attached: function() {
this._setColors();
},
/**
* Set the colors of the elements to the ones specified by the user, use defaults if nothing was specified
*/
_setColors() {
// default to var(--paper-grey-300)
this.$.background.style.fill = this.backgroundColor? this.backgroundColor : '#e0e0e0';
if (!this.progressColors || this.progressColors.length !== 3) {
// default to var(--paper-red-500), var(--paper-yellow-500) and var(--paper-green-500)
this.progressColors = ['#f44336', '#ffeb3b', '#4caf50'];
}
var lowProgress = Polymer.dom(this.root).querySelector('.low');
if (lowProgress) {
lowProgress.style.fill = this.progressColors[0];
}
var mediumProgress = Polymer.dom(this.root).querySelector('.medium');
if (mediumProgress) {
mediumProgress.style.fill = this.progressColors[1];
}
var highProgress = Polymer.dom(this.root).querySelector('.high');
if (highProgress) {
highProgress.style.fill = this.progressColors[2];
}
},
_computeDiameter: function(radius) {
return 2 * radius;
},
_computeTransform: function(radius) {
return "translate(" + radius + ", " + radius + ")";
},
_computeProgressLevel: function(percentage) {
if (percentage <= .33) {
return 'low';
}
if (percentage <= .66) {
return 'medium';
}
return 'high';
},
_radiusChanged: function(oldVal, newVal) {
this._onRadiusChanged();
this._onPercentageChanged();
},
_percentageChanged: function(oldVal, newVal) {
this._onPercentageChanged();
},
_onRadiusChanged: function() {
this.progressArc = d3.svg.arc()
.startAngle(0)
.innerRadius(9/10 * this.radius)
.outerRadius(this.radius);
this.backgroundArc = d3.svg.arc()
.startAngle(0)
.innerRadius(0.825 * this.radius)
.outerRadius(0.85 * this.radius);
this.$.current.style.fontSize = this.radius/2 + 'px';
this.$.goal.style.fontSize = this.radius/5 + 'px';
this.$.type.style.fontSize = this.radius/4 + 'px';
this.$.type.style.width = 2 * this.radius + 'px';
this.$.caption.style.fontSize = this.radius/5 + 'px';
this.$.caption.style.width = 2 * this.radius + 'px';
this.$.background.setAttribute('d', this.backgroundArc.endAngle(2 * Math.PI)());
},
_onPercentageChanged: function() {
if (typeof this.percentage == 'undefined') {
return;
}
this.percentage = Math.min(1, Math.max(0, this.percentage));
var i = d3.interpolate(this._progress, this.percentage);
d3.select(this).transition().tween(this.$.progress, function() {
return function(t) {
this._progress = i(t);
this.$.progress.setAttribute('d', this.progressArc.endAngle(2 * Math.PI * this._progress)());
}.bind(this);
}.bind(this));
}
});
})();
</script>