Merge pull request #136 from apertureless/feature/scatter_chart
Feature/scatter chart
@@ -247,6 +247,10 @@ export default Line.extend({
|
||||
|
||||

|
||||
|
||||
### Scatter
|
||||
|
||||

|
||||
|
||||
## Build Setup
|
||||
|
||||
``` bash
|
||||
|
||||
BIN
assets/bar.png
Normal file → Executable file
|
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 25 KiB |
BIN
assets/bubble.png
Normal file → Executable file
|
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 26 KiB |
BIN
assets/doughnut.png
Normal file → Executable file
|
Before Width: | Height: | Size: 91 KiB After Width: | Height: | Size: 41 KiB |
BIN
assets/line.png
Normal file → Executable file
|
Before Width: | Height: | Size: 125 KiB After Width: | Height: | Size: 31 KiB |
BIN
assets/pie.png
Normal file → Executable file
|
Before Width: | Height: | Size: 97 KiB After Width: | Height: | Size: 76 KiB |
BIN
assets/polar.png
Normal file → Executable file
|
Before Width: | Height: | Size: 200 KiB After Width: | Height: | Size: 87 KiB |
BIN
assets/radar.png
Normal file → Executable file
|
Before Width: | Height: | Size: 180 KiB After Width: | Height: | Size: 75 KiB |
BIN
assets/scatter.png
Executable file
|
After Width: | Height: | Size: 43 KiB |
@@ -287,6 +287,12 @@ Sometimes you need more control over chart.js. Thats why you can access the char
|
||||
|
||||

|
||||
|
||||
### Scatter
|
||||
|
||||
This chart has a different data structure then the others. Right now the reactive Mixins are not working for this chart type.
|
||||
|
||||

|
||||
|
||||
|
||||
## Explanation of Different Builds
|
||||
There are three different entry points. It depends on which build setup do you have. The dependencies are bundled or required as a peerDependency.
|
||||
|
||||
69
src/BaseCharts/Scatter.js
Normal file
@@ -0,0 +1,69 @@
|
||||
import Vue from 'vue'
|
||||
import Chart from 'chart.js'
|
||||
import { mergeOptions } from '../helpers/options'
|
||||
|
||||
export default Vue.extend({
|
||||
render: function (createElement) {
|
||||
return createElement(
|
||||
'div',
|
||||
[
|
||||
createElement(
|
||||
'canvas', {
|
||||
attrs: {
|
||||
id: this.chartId,
|
||||
width: this.width,
|
||||
height: this.height
|
||||
},
|
||||
ref: 'canvas'
|
||||
}
|
||||
)
|
||||
]
|
||||
)
|
||||
},
|
||||
|
||||
props: {
|
||||
chartId: {
|
||||
default: 'scatter-chart',
|
||||
type: String
|
||||
},
|
||||
width: {
|
||||
default: 400,
|
||||
type: Number
|
||||
},
|
||||
height: {
|
||||
default: 400,
|
||||
type: Number
|
||||
}
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
defaultOptions: {
|
||||
scales: {
|
||||
xAxes: [{
|
||||
type: 'linear',
|
||||
position: 'bottom'
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
renderChart (data, options) {
|
||||
let chartOptions = mergeOptions(this.defaultOptions, options)
|
||||
|
||||
this._chart = new Chart(
|
||||
this.$refs.canvas.getContext('2d'), {
|
||||
type: 'scatter',
|
||||
data: data,
|
||||
options: chartOptions
|
||||
}
|
||||
)
|
||||
this._chart.generateLegend()
|
||||
}
|
||||
},
|
||||
beforeDestroy () {
|
||||
this._chart.destroy()
|
||||
}
|
||||
})
|
||||
@@ -1,23 +1,54 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<h1 style="text-align:center;margin:40px 0;">Barchart</h1>
|
||||
<bar-example></bar-example>
|
||||
<h1 style="text-align:center;margin:40px 0;">Barchart with reactive mixing for live data</h1>
|
||||
<reactive-example></reactive-example>
|
||||
<h1 style="text-align:center;margin:40px 0;">Barchart with reactive mixing for live data as props</h1>
|
||||
<reactive-prop-example :chart-data="dataPoints"></reactive-prop-example>
|
||||
<h1 style="text-align:center;margin:40px 0;">Linechart</h1>
|
||||
<line-example></line-example>
|
||||
<h1 style="text-align:center;margin:40px 0;">Doughnutchart</h1>
|
||||
<doughnut-example></doughnut-example>
|
||||
<h1 style="text-align:center;margin:40px 0;">Piechart</h1>
|
||||
<pie-example></pie-example>
|
||||
<h1 style="text-align:center;margin:40px 0;">Radarchart</h1>
|
||||
<radar-example></radar-example>
|
||||
<h1 style="text-align:center;margin:40px 0;">Polararea</h1>
|
||||
<polar-area-example></polar-area-example>
|
||||
<h1 style="text-align:center;margin:40px 0;">Bubblechart</h1>
|
||||
<bubble-example></bubble-example>
|
||||
<div class="Chart">
|
||||
<h1 style="text-align:center;">Barchart</h1>
|
||||
<bar-example></bar-example>
|
||||
</div>
|
||||
|
||||
<div class="Chart">
|
||||
<h1 style="text-align:center;">Barchart with reactive mixing for live data</h1>
|
||||
<reactive-example></reactive-example>
|
||||
</div>
|
||||
|
||||
<div class="Chart">
|
||||
<h1 style="text-align:center;">Barchart with reactive mixing for live data as props</h1>
|
||||
<reactive-prop-example :chart-data="dataPoints"></reactive-prop-example>
|
||||
</div>
|
||||
|
||||
<div class="Chart">
|
||||
<h1 style="text-align:center;">Linechart</h1>
|
||||
<line-example></line-example>
|
||||
</div>
|
||||
|
||||
<div class="Chart">
|
||||
<h1 style="text-align:center;">Doughnutchart</h1>
|
||||
<doughnut-example></doughnut-example>
|
||||
</div>
|
||||
|
||||
<div class="Chart">
|
||||
<h1 style="text-align:center;">Piechart</h1>
|
||||
<pie-example></pie-example>
|
||||
</div>
|
||||
|
||||
<div class="Chart">
|
||||
<h1 style="text-align:center;">Radarchart</h1>
|
||||
<radar-example></radar-example>
|
||||
</div>
|
||||
|
||||
<div class="Chart">
|
||||
<h1 style="text-align:center;">Polararea</h1>
|
||||
<polar-area-example></polar-area-example>
|
||||
</div>
|
||||
|
||||
<div class="Chart">
|
||||
<h1 style="text-align:center;">Bubblechart</h1>
|
||||
<bubble-example></bubble-example>
|
||||
</div>
|
||||
|
||||
<div class="Chart">
|
||||
<h1 style="text-align:center;">Scatter Chart</h1>
|
||||
<scatter-example></scatter-example>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -31,6 +62,7 @@
|
||||
import BubbleExample from './BubbleExample'
|
||||
import ReactiveExample from './ReactiveExample'
|
||||
import ReactivePropExample from './ReactivePropExample'
|
||||
import ScatterExample from './ScatterExample'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -42,7 +74,8 @@
|
||||
PolarAreaExample,
|
||||
BubbleExample,
|
||||
ReactiveExample,
|
||||
ReactivePropExample
|
||||
ReactivePropExample,
|
||||
ScatterExample
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
@@ -79,4 +112,21 @@
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-family: 'Helvetica', Arial;
|
||||
color: #464646;
|
||||
text-transform: uppercase;
|
||||
border-bottom: 1px solid #f1f1f1;
|
||||
padding-bottom: 15px;
|
||||
font-size: 28px;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.Chart {
|
||||
padding: 20px;
|
||||
box-shadow: 0px 0px 20px 2px rgba(0, 0, 0, .4);
|
||||
border-radius: 20px;
|
||||
margin: 50px 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
53
src/examples/ScatterExample.js
Normal file
@@ -0,0 +1,53 @@
|
||||
import Scatter from '../BaseCharts/Scatter'
|
||||
|
||||
export default Scatter.extend({
|
||||
mounted () {
|
||||
this.renderChart({
|
||||
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
|
||||
datasets: [{
|
||||
label: 'Scatter Dataset 1',
|
||||
fill: false,
|
||||
borderColor: '#f87979',
|
||||
backgroundColor: '#f87979',
|
||||
data: [{
|
||||
x: -2,
|
||||
y: 4
|
||||
}, {
|
||||
x: -1,
|
||||
y: 1
|
||||
}, {
|
||||
x: 0,
|
||||
y: 0
|
||||
}, {
|
||||
x: 1,
|
||||
y: 1
|
||||
}, {
|
||||
x: 2,
|
||||
y: 4
|
||||
}]
|
||||
},
|
||||
{
|
||||
label: 'Scatter Dataset 2',
|
||||
fill: false,
|
||||
borderColor: '#7acbf9',
|
||||
backgroundColor: '#7acbf9',
|
||||
data: [{
|
||||
x: -2,
|
||||
y: -4
|
||||
}, {
|
||||
x: -1,
|
||||
y: -1
|
||||
}, {
|
||||
x: 0,
|
||||
y: 1
|
||||
}, {
|
||||
x: 1,
|
||||
y: -1
|
||||
}, {
|
||||
x: 2,
|
||||
y: -4
|
||||
}]
|
||||
}]
|
||||
}, {responsive: true, maintainAspectRatio: false})
|
||||
}
|
||||
})
|
||||
64
test/unit/specs/Scatter.spec.js
Normal file
@@ -0,0 +1,64 @@
|
||||
import Vue from 'vue'
|
||||
import ScatterChart from 'src/examples/ScatterExample'
|
||||
|
||||
describe('ScatterChart', () => {
|
||||
let el
|
||||
|
||||
beforeEach(() => {
|
||||
el = document.createElement('div')
|
||||
})
|
||||
|
||||
it('should render a canvas', () => {
|
||||
const vm = new Vue({
|
||||
render: function (createElement) {
|
||||
return createElement(
|
||||
ScatterChart
|
||||
)
|
||||
},
|
||||
components: { ScatterChart }
|
||||
}).$mount(el)
|
||||
|
||||
expect(vm.$el.querySelector('#scatter-chart')).not.to.be.an('undefined')
|
||||
expect(vm.$el.querySelector('canvas')).not.to.be.an('undefined')
|
||||
expect(vm.$el.querySelector('canvas')).not.to.be.an('null')
|
||||
expect(vm.$el.querySelector('canvas')).to.exist
|
||||
})
|
||||
|
||||
it('should change id based on prop', () => {
|
||||
const vm = new Vue({
|
||||
render: function (createElement) {
|
||||
return createElement(
|
||||
ScatterChart, {
|
||||
props: {
|
||||
chartId: 'linechartprop'
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
components: { ScatterChart }
|
||||
}).$mount(el)
|
||||
|
||||
expect(vm.$el.querySelector('#linechartprop')).not.to.be.an('undefined')
|
||||
})
|
||||
|
||||
it('should destroy chart instance', (done) => {
|
||||
const vm = new Vue({
|
||||
render: function (createElement) {
|
||||
return createElement(
|
||||
ScatterChart
|
||||
)
|
||||
},
|
||||
components: { ScatterChart }
|
||||
}).$mount(el)
|
||||
|
||||
expect(vm.$children[0]._chart.chart.ctx).not.to.be.null
|
||||
|
||||
vm.$destroy()
|
||||
|
||||
vm.$nextTick(() => {
|
||||
vm.$forceUpdate()
|
||||
expect(vm.$children[0]._chart.chart.ctx).to.be.null
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||