Last active
February 23, 2017 17:37
-
-
Save onlymejosh/507a18e1705319126f57c71d41cec3cc to your computer and use it in GitHub Desktop.
New Twiddle
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Ember from 'ember'; | |
export default Ember.Controller.extend({ | |
appName: 'Ember Twiddle' | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Component from 'ember-component'; | |
import computed from 'ember-computed'; | |
import EmberObject from 'ember-object'; | |
import { htmlSafe } from 'ember-string'; | |
import layout from './template'; | |
import set from 'ember-metal/set'; | |
import run from 'ember-runloop'; | |
import { stack, stackOrderNone, stackOffsetNone} from 'd3-shape'; | |
import { scaleBand, scaleLinear, scaleOrdinal } from 'd3-scale'; | |
import { max, range } from 'd3-array'; | |
export default Component.extend({ | |
layout, | |
width: 600, | |
height: 300, | |
color: scaleOrdinal([ | |
'#E9008B', | |
'#CE3C1D', | |
'#F05522', | |
'#F4891E', | |
'#FFC60A', | |
'#DECD20', | |
'#BBD530', | |
'#94C73B', | |
'#00823C', | |
'#46B85C', | |
'#00B38C', | |
'#5FC3B0', | |
'#478CCB', | |
'#26C4F4', | |
'#3D66B0', | |
'#4151A3', | |
'#69236B', | |
'#59439B', | |
'#6E3E7B', | |
'#894772', | |
'#BF5A88', | |
'#ED589F' | |
]), | |
/** | |
* | |
* @property keys | |
* @return Returns an array of keys for which the data is distributed | |
* Example: | |
* keys: computed(() => ['0.0-20.0', '20.0-40.0', '40.0-60.0', '60.0-80.0', '80.0-101.0']), | |
* | |
*/ | |
keys: computed(() => ["apples", "bananas", "cherries", "dates"]), | |
/** | |
* | |
* @property data | |
* @return Returns a flat array of distributed data. | |
* Example: | |
* data: computed(() => [ | |
* { timestamp: new Date(2015, 2, 1), apples: 200, bananas: 100, cherries: 300, dates: 300 }, | |
* ]), | |
* | |
*/ | |
data: computed(() => [ | |
{timestamp: new Date(2015, 0, 1), apples: 3840, bananas: 1920, cherries: 960, dates: 400}, | |
{timestamp: new Date(2015, 1, 1), apples: 1600, bananas: 1440, cherries: 960, dates: 400}, | |
{timestamp: new Date(2015, 2, 1), apples: 640, bananas: 960, cherries: 640, dates: 400}, | |
{timestamp: new Date(2015, 3, 1), apples: 320, bananas: 480, cherries: 640, dates: 400} | |
]), | |
xScale: computed('data.[]', 'width', function() { | |
return scaleBand() | |
.domain(range(this.get('data.length'))) | |
.rangeRound([0, this.get('width')]) | |
.padding(0.05); | |
}), | |
yScale: computed('data.[]', 'height', function() { | |
return scaleLinear().range([0, this.get('height')]); | |
}), | |
d3Data: computed('data.[]', 'keys.[]', 'yScale', 'xScale', function() { | |
let { data, keys } = this.getProperties('data', 'keys'); | |
if (!(data && data.length || keys && keys.length)) { return false; } | |
let stackedData = stack() | |
.keys(this.get('keys')) | |
.order(stackOrderNone) | |
.offset(stackOffsetNone); | |
let layers = stackedData(this.get('data')); | |
console.log('data change') | |
this.get('yScale').domain([0, max(layers[layers.length - 1], (d) => d[1]) ]).nice(); | |
let bandwidth = this.get('xScale').bandwidth(); | |
let d3Data = layers.map((layer) => { | |
return EmberObject.create({ | |
key: layer.key, | |
isLowLight: false, // TODO: More descriptive naming? Used to define whether the series should be | |
values: layer.map((item, i) => { | |
let [y0, y1] = item; | |
let { data } = item; | |
let height = this.get('yScale')(y1 - y0); | |
let x = this.get('xScale')(i); | |
return { | |
color: this.get('color')(layer.index), | |
width: bandwidth, | |
height, | |
x, | |
y: this.get('height') - height - this.get('yScale')(y0), | |
label: `${layer.key} x ${data[layer.key]} on ${data.timestamp}`, | |
}; | |
}), | |
}); | |
}); | |
return d3Data; | |
}), | |
_positionTooltip(tooltipOffset) { | |
let $tooltip = this.$('.tooltip'); | |
let width = $tooltip.width(); | |
tooltipOffset.left -= width / 2; // position tooltip in the middle | |
let delta = window.innerWidth - (tooltipOffset.left + width); | |
// ensure we're not off the left or right | |
if (delta < 0) { | |
tooltipOffset.left += delta; | |
} | |
if (tooltipOffset.left < 0) { | |
tooltipOffset.arrowPosition = 0.5 - (Math.abs(tooltipOffset.left) / width); | |
tooltipOffset.left = 0; | |
} | |
return tooltipOffset; | |
}, | |
setActive(key) { | |
this.get('d3Data').setEach('isLowLight', true); | |
const activeSeries = this.get('d3Data').findBy('key',key) | |
console.log(activeSeries) | |
activeSeries.set('isLowLight', false) | |
console.log(this.get('d3Data')) | |
}, | |
actions: { | |
showTooltip(tooltipText, left, top) { | |
const position = this._positionTooltip({ left, top }); | |
this.setProperties({ | |
tooltipLocation: position, | |
tooltipStyle: htmlSafe(`left: ${position.left}px; top: ${position.top}px; display: block;`), | |
tooltipText, | |
}); | |
}, | |
hideTooltip() { | |
this.set('tooltipLocation', null); | |
this.set('tooltipStyle', null); | |
}, | |
onSeriesMouseEnter(key) { | |
run.scheduleOnce('afterRender', this, 'setActive', key) | |
}, | |
onSeriesMouseLeave(key) { | |
this.get('d3Data').setEach('isLowLight', false); | |
} | |
} | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
body { | |
margin: 12px 16px; | |
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; | |
font-size: 12pt; | |
} | |
.lighten { | |
opacity: 0.1; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"version": "0.11.0", | |
"EmberENV": { | |
"FEATURES": {} | |
}, | |
"options": { | |
"use_pods": true, | |
"enable-testing": false | |
}, | |
"dependencies": { | |
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.js", | |
"ember": "2.10.2", | |
"ember-data": "2.11.0", | |
"ember-template-compiler": "2.10.2", | |
"ember-testing": "2.10.2" | |
}, | |
"addons": { | |
"ember-d3": "0.3.2" | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Component from 'ember-component'; | |
import layout from './template'; | |
import run from 'ember-runloop'; | |
export default Component.extend({ | |
layout, | |
attributeBindings: ['color:fill', 'height', 'width', 'x', 'y'], | |
tagName: 'rect', | |
// Default Properties | |
color: 'red', | |
height: 0, | |
width: 0, | |
x: 0, | |
y: 0, | |
mouseEnter(event) { | |
const x = this.$().position().left + (this.get('width') / 2); | |
this.get('onMouseEnter')(x, event.pageY); | |
}, | |
mouseLeave() { | |
this.get('onMouseLeave')(); | |
}, | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment