Skip to content

Instantly share code, notes, and snippets.

@bantic
Last active August 12, 2019 19:44
Show Gist options
  • Save bantic/5ea29b4db2f460291d5c1d9902321141 to your computer and use it in GitHub Desktop.
Save bantic/5ea29b4db2f460291d5c1d9902321141 to your computer and use it in GitHub Desktop.
donut charts
import Ember from 'ember';
export default Ember.Component.extend({
actions: {
update(e) {
let srcValue = e.target.value;
let parsedValue = parseFloat(srcValue);
if (!Number.isNaN(parsedValue)) {
this.sendAction('didChange', parsedValue);
}
}
}
});
import Ember from 'ember';
function d2r(degrees) {
// PI rad = 180 deg
return Math.PI * (degrees/180);
}
export default Ember.Component.extend({
tagName:'',
largeSweep: Ember.computed('startDegrees', 'endDegrees', function() {
return this.get('endDegrees') - this.get('startDegrees') > 180 ? 1 : 0;
}),
coords: Ember.computed('xCenter','yCenter','innerRadius','outerRadius','startDegrees','endDegrees', function() {
let xCenter = this.get('xCenter');
let yCenter = this.get('yCenter');
console.log('SD',this.get('startDegrees'));
let startDegrees = this.get('startDegrees') - 90;
let endDegrees = this.get('endDegrees') - 90;
let startRads = d2r(startDegrees);
let endRads = d2r(endDegrees);
let outerR = this.get('outerRadius');
let innerR = this.get('innerRadius');
let coords = {
outer: {
start: {
x: xCenter + outerR * Math.cos(startRads),
y: yCenter + outerR * Math.sin(startRads),
},
end: {
x: xCenter + outerR * Math.cos(endRads),
y: yCenter + outerR * Math.sin(endRads)
},
},
inner: {
start: {
x: xCenter + innerR * Math.cos(startRads),
y: yCenter + innerR * Math.sin(startRads),
},
end: {
x: xCenter + innerR * Math.cos(endRads),
y: yCenter + innerR * Math.sin(endRads),
}
}
};
console.log('coords:',coords);
return coords;
})
});
import Ember from 'ember';
const SECTION_NAMES = [
'alpha',
'beta',
'gamma',
'foo',
'bar',
'baz'
];
const COLORS = [
'red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet'
];
function createSections() {
let sections = [];
let remainingPct = 1.0;
let colors = COLORS.slice().sort(() => 0.5 - Math.random());
console.log('COLORS',colors);
SECTION_NAMES.forEach((name, idx) => {
let pct;
if (idx === SECTION_NAMES.length - 1) {
pct = remainingPct;
} else {
do {
pct = Math.random() * 0.25;
} while (pct > remainingPct);
}
let startDegrees = idx === 0 ? 0 : sections[idx-1].endDegrees;
let endDegrees = startDegrees + pct * 360;
sections.push({
name,
pct,
startDegrees,
endDegrees,
color: colors[idx % colors.length]
});
remainingPct -= pct;
});
return sections;
}
export default Ember.Controller.extend({
appName: 'Ember Twiddle',
sections: createSections(),
innerRadius: 100,
outerRadius: 120,
actions: {
recalculate() {
this.set('sections', createSections());
}
}
});
import Ember from 'ember';
function degrees2radians(degrees) {
// PI rad = 180 deg
return Math.PI * (degrees/180);
}
export function angleToCoords(params, {degrees,xCenter,yCenter,radius}) {
let rads = degrees2radians(degrees);
let x = xCenter + radius * Math.cos(rads);
let y = yCenter + radius * Math.sin(rads);
return `${x} ${y}`;
}
export default Ember.Helper.helper(angleToCoords);
import Ember from 'ember';
export function formatPct([pct]/*, hash*/) {
return (pct*100).toFixed(0) + '%';
}
export default Ember.Helper.helper(formatPct);
import Ember from 'ember';
export function numToFixed([num,places]/*, hash*/) {
return num.toFixed(places);
}
export default Ember.Helper.helper(numToFixed);
import Ember from 'ember';
import { angleToCoords } from './angle-to-coords';
export function svgArc(params, {xCenter,yCenter,radius,startDegrees,endDegrees}) {
startDegrees -= 90;
endDegrees -= 90;
let largeArc = endDegrees - startDegrees >= 180 ? 1 : 0;
// let largeArc = endDegrees - startDegrees >= 90 ? 1 : 0;
return `
M ${angleToCoords([], {radius,xCenter,yCenter,degrees:startDegrees})}
A ${radius} ${radius} 0 ${largeArc} 1 ${angleToCoords([], {radius,xCenter,yCenter,degrees:endDegrees})}
`;
return params;
}
export default Ember.Helper.helper(svgArc);
body {
margin: 12px 16px;
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 12pt;
}
ul {
list-style: none;
margin: 0;
padding: 0;
}
li {
padding: 0.5em;
color: white;
}
li[data-color="yellow"] {
color: black;
}
.donut-path {
stroke-width: 2px;
stroke: white;
}
<h1>Ember Donut Example</h1>
<ul>
{{#each sections as |section|}}
<li style="background-color: {{section.color}}" data-color={{section.color}}>{{section.name}} {{format-pct section.pct}}: {{num-to-fixed section.startDegrees 0}}-&gt;{{num-to-fixed section.endDegrees 0}}</li>
{{/each}}
</ul>
<br>
<button {{action 'recalculate'}}>Reshuffle</button>
<br><br>
Inner Radius {{numeric-input value=innerRadius didChange=(action (mut innerRadius))}}<br>
Outer Radius {{numeric-input value=outerRadius didChange=(action (mut outerRadius))}}
<br>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="400" height="400" style="border: 1px solid black">
{{#each sections as |section|}}
{{svg/donut-arc xCenter=200 yCenter=200 outerRadius=outerRadius innerRadius=innerRadius startDegrees=section.startDegrees endDegrees=section.endDegrees color=section.color}}
{{/each}}
</svg>
<input value={{value}} type="number" oninput={{action 'update'}} />
<path
class="donut-path"
d="
M {{coords.inner.start.x}} {{coords.inner.start.y}}
L {{coords.outer.start.x}} {{coords.outer.start.y}}
A {{outerRadius}} {{outerRadius}} 0 {{largeSweep}} 1 {{coords.outer.end.x}} {{coords.outer.end.y}}
L {{coords.inner.end.x}} {{coords.inner.end.y}}
A {{innerRadius}} {{innerRadius}} 0 {{largeSweep}} 0 {{coords.inner.start.x}} {{coords.inner.start.y}}
Z
" fill="{{color}}" />
{
"version": "0.15.1",
"EmberENV": {
"FEATURES": {}
},
"options": {
"use_pods": false,
"enable-testing": false
},
"dependencies": {
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js",
"ember": "3.4.3",
"ember-template-compiler": "3.4.3",
"ember-testing": "3.4.3"
},
"addons": {
"ember-data": "3.4.2"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment