Commit 94f7bbb4 authored by Sascha Herzinger's avatar Sascha Herzinger
Browse files

Removing animations because they are resource hungry and hard to maintain.

parent 2aa63cb3
Pipeline #2933 passed with stages
in 3 minutes and 12 seconds
......@@ -4671,11 +4671,6 @@
"resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
"integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU="
},
"gsap": {
"version": "1.20.3",
"resolved": "https://registry.npmjs.org/gsap/-/gsap-1.20.3.tgz",
"integrity": "sha512-WICK7628LOKYIzcDzN0fGH44uF9TGzUhZkltlnsOivwnb65ApgFXN0hnsEXHQerl+TVGhv7h9glyTW5LWlEypQ=="
},
"handle-thing": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz",
......@@ -6649,9 +6644,9 @@
"dev": true
},
"popper.js": {
"version": "1.12.5",
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.12.5.tgz",
"integrity": "sha512-6R2eXIy1xYukMNutoD+y/Gj0IpjEQhivyZonm5Vz0Fp8jdc7kvheKCvpM/t+PxqKb7VbLVnvPVEdTyslEb7f6w=="
"version": "1.12.9",
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.12.9.tgz",
"integrity": "sha1-DfvC3/lsRRuzMu3Pz6r1ZtMx1bM="
},
"portfinder": {
"version": "1.0.13",
......@@ -8637,11 +8632,11 @@
}
},
"tippy.js": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/tippy.js/-/tippy.js-1.3.0.tgz",
"integrity": "sha512-Vo94+MKDfISTp7AKsXeQ1A5Blf9O38guVh8pGFwJjeP+r+OgWuUykMgQNu/PhWcafz8Jrz4WMVHIpTQLuMa2YQ==",
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/tippy.js/-/tippy.js-2.0.5.tgz",
"integrity": "sha512-Dc2SwNKZzDFcS4WR7tjLUhPX2FhlHakJvfm6452xhwiPi1iRzWfOOkzvmg837js0kBO1trYZBopYYJOdZBnk1g==",
"requires": {
"popper.js": "1.12.5"
"popper.js": "1.12.9"
}
},
"tmp": {
......
import types from './mutation-types'
import RequestManager from '../services/request-manager'
import { TweenLite } from 'gsap'
export default {
/**
......@@ -85,13 +84,5 @@ export default {
*/
addControlPanel: (context, vm) => {
context.commit(types.ADD_CONTROL_PANEL, {vm})
},
/**
* Commits a change to the animation state to deterime whether or not visuals are animated
* @param context The context of the action.
* @param enabled Whether or not to animate
*/
setAnimation: (context, enabled) => {
context.commit(types.SET_ANIMATION, {enabled})
}
}
......@@ -4,6 +4,5 @@ export default {
subsets: state => state.subsets,
requestManager: state => state.requestManager,
controlPanels: state => state.controlPanels,
filter: state => name => state.filters[name],
animation: state => state.animation
filter: state => name => state.filters[name]
}
......@@ -5,6 +5,5 @@ export default {
SET_FILTER: 'SET_FILTER',
SET_TASK: 'SET_TASK',
UNSET_TASK: 'UNSET_TASK',
ADD_CONTROL_PANEL: 'ADD_CONTROL_PANEL',
SET_ANIMATION: 'SET_ANIMATION'
ADD_CONTROL_PANEL: 'ADD_CONTROL_PANEL'
}
......@@ -30,8 +30,5 @@ export default {
},
[types.ADD_CONTROL_PANEL] (state, {vm}) {
state.controlPanels.push(vm)
},
[types.SET_ANIMATION] (state, {enabled}) {
state.animation = enabled
}
}
......@@ -14,8 +14,7 @@ const state = {
subsets: [],
filters: {
ids: []
},
animation: true
}
}
export default new Vuex.Store({
......
......@@ -33,7 +33,7 @@
<g class="fjs-boxplot-axis fjs-y-axis"></g>
<g class="fjs-box"
:transform="`translate(${scales.x(label)}, 0)`"
v-tooltip="{position: 'bottom'}"
v-tooltip="{placement: 'bottom'}"
:title="label"
:data-label="label"
@click="setIDFilter(label)"
......@@ -42,61 +42,61 @@
v-for="label in labels" >
<line class="fjs-upper-whisker"
:title="results.statistics[label].u_wsk"
v-tooltip="{position: 'right'}"
v-tooltip="{placement: 'right'}"
:x1="- boxplotWidth / 6"
:y1="tweened.boxes[label].u_wsk"
:y1="boxes[label].u_wsk"
:x2="boxplotWidth / 6"
:y2="tweened.boxes[label].u_wsk">
:y2="boxes[label].u_wsk">
</line>
<line class="fjs-lower-whisker"
:title="results.statistics[label].l_wsk"
v-tooltip="{position: 'right'}"
v-tooltip="{placement: 'right'}"
:x1="- boxplotWidth / 6"
:y1="tweened.boxes[label].l_wsk"
:y1="boxes[label].l_wsk"
:x2="boxplotWidth / 6"
:y2="tweened.boxes[label].l_wsk">
:y2="boxes[label].l_wsk">
</line>
<line class="fjs-upper-quartile"
:title="results.statistics[label].u_qrt"
v-tooltip="{position: 'left'}"
v-tooltip="{placement: 'left'}"
:x1="- boxplotWidth / 2"
:y1="tweened.boxes[label].u_qrt"
:y1="boxes[label].u_qrt"
:x2="boxplotWidth / 2"
:y2="tweened.boxes[label].u_qrt">
:y2="boxes[label].u_qrt">
</line>
<line class="fjs-lower-quartile"
:title="results.statistics[label].l_qrt"
v-tooltip="{position: 'left'}"
v-tooltip="{placement: 'left'}"
:x1="- boxplotWidth / 2"
:y1="tweened.boxes[label].l_qrt"
:y1="boxes[label].l_qrt"
:x2="boxplotWidth / 2"
:y2="tweened.boxes[label].l_qrt">
:y2="boxes[label].l_qrt">
</line>
<line class="fjs-median"
:title="results.statistics[label].median"
v-tooltip="{position: 'right'}"
v-tooltip="{placement: 'right'}"
:x1="- boxplotWidth / 2"
:y1="tweened.boxes[label].median"
:y1="boxes[label].median"
:x2="boxplotWidth / 2"
:y2="tweened.boxes[label].median">
:y2="boxes[label].median">
</line>
<line class="fjs-antenna"
:x1="0"
:y1="tweened.boxes[label].u_wsk"
:y1="boxes[label].u_wsk"
:x2="0"
:y2="tweened.boxes[label].l_wsk">
:y2="boxes[label].l_wsk">
</line>
<rect class="fjs-above-median-box"
:x="- boxplotWidth / 2"
:y="tweened.boxes[label].u_qrt"
:y="boxes[label].u_qrt"
:width="boxplotWidth"
:height="tweened.boxes[label].median - tweened.boxes[label].u_qrt">
:height="boxes[label].median - boxes[label].u_qrt">
</rect>
<rect class="fjs-below-median-box"
:x="- boxplotWidth / 2"
:y="tweened.boxes[label].median"
:y="boxes[label].median"
:width="boxplotWidth"
:height="tweened.boxes[label].l_qrt - tweened.boxes[label].median">
:height="boxes[label].l_qrt - boxes[label].median">
</rect>
<circle class="fjs-points"
:title="point.tooltip"
......@@ -125,7 +125,6 @@
import store from '../../store/store'
import runAnalysis from '../mixins/run-analysis'
import * as d3 from 'd3'
import { TimelineLite } from 'gsap'
import deepFreeze from 'deep-freeze-strict'
import { truncateTextUntil } from '../mixins/utils'
import tooltip from '../directives/tooltip'
......@@ -149,9 +148,6 @@
results: {
data: [],
statistics: {}
},
tweened: {
boxes: {}
}
}
},
......@@ -291,20 +287,6 @@
// statement. This helps with the integration into the Vue component lifecycle. E.g.: an animation can't be
// applied to an element that does not exist yet.
watch: {
'boxes': {
handler: function (newBoxes) {
const labels = Object.keys(newBoxes)
const timeline = new TimelineLite()
labels.forEach(label => {
if (typeof this.tweened.boxes[label] === 'undefined') {
this.$set(this.tweened.boxes, label, newBoxes[label])
} else {
timeline.to(this.tweened.boxes[label], store.getters.animation ? 0.5 : 0, newBoxes[label], 0)
}
})
timeline.play()
}
},
'args': {
handler: function () {
if (this.validArgs && !this.hasSetFilter) {
......@@ -343,10 +325,10 @@
})
},
showTooltip (label) {
this.getTippyInstances(label).forEach(d => d.tip.show(d.tip.getPopperElement(d.el)))
this.getTippyInstances(label).forEach(d => d.el._tippy.show())
},
hideTooltip (label) {
this.getTippyInstances(label).forEach(d => d.tip.hide(d.tip.getPopperElement(d.el)))
this.getTippyInstances(label).forEach(d => d.el._tippy.hide())
},
update_numData (ids) {
this.numData = ids
......
......@@ -49,18 +49,30 @@
:fill="categoryColors[categories.indexOf(point.category) % categoryColors.length]"
:title="point.tooltip"
v-tooltip
v-for="point in tweened.points">
v-for="point in points">
</polygon>
<line class="fjs-lin-reg-line"
:x1="regLine.x1"
:x2="regLine.x2"
:y1="regLine.y1"
:y2="regLine.y2"
:title="regLine.tooltip"
v-tooltip="{followCursor: true}"
:x1="tweened.regLine.x1"
:x2="tweened.regLine.x2"
:y1="tweened.regLine.y1"
:y2="tweened.regLine.y2">
v-tooltip="{followCursor: true}">
</line>
<polyline class="fjs-histogram-polyline fjs-bottom" points=""></polyline>
<polyline class="fjs-histogram-polyline fjs-left" points=""></polyline>
<rect class="fjs-histogram fjs-histogram-bottom"
:width="bin.width"
:height="bin.height"
:x="bin.x"
:y="bin.y"
v-for="bin in histogram.bottom">
</rect>
<rect class="fjs-histogram fjs-histogram-left"
:width="bin.width"
:height="bin.height"
:x="bin.x"
:y="bin.y"
v-for="bin in histogram.left">
</rect>
</g>
</svg>
......@@ -70,12 +82,11 @@
<script>
import DataBox from '../components/DataBox.vue'
import ControlPanel from '../components/ControlPanel.vue'
import { getPolygonPointsForSubset, tweenGroup } from '../mixins/utils'
import { getPolygonPointsForSubset } from '../mixins/utils'
import Chart from '../components/Chart.vue'
import store from '../../store/store'
import runAnalysis from '../mixins/run-analysis'
import * as d3 from 'd3'
import { TweenLite } from 'gsap'
import tooltip from '../directives/tooltip.js'
import deepFreeze from 'deep-freeze-strict'
export default {
......@@ -112,10 +123,6 @@
data: []
},
selectedPoints: [],
tweened: {
regLine: {x1: 0, x2: 0, y1: 0, y2: 0},
points: []
},
hasSetFilter: false
}
},
......@@ -137,16 +144,16 @@
}
},
margin () {
const left = this.width / 3
const left = this.width / 4
const top = this.height / 20
const right = this.width / 20
const bottom = this.height / 3
return { left, top, right, bottom }
const bottom = this.height / 4
return {left, top, right, bottom}
},
padded () {
const width = this.width - this.margin.left - this.margin.right
const height = this.height - this.margin.top - this.margin.bottom
return { width, height }
return {width, height}
},
categories () {
return [...new Set(this.shownResults.data.map(d => d.category))]
......@@ -185,7 +192,7 @@
return [yExtent[0] - yPadding, yExtent[1] + yPadding]
})())
.range([this.padded.height, 0])
return { x, y }
return {x, y}
},
axis () {
const x1 = d3.axisTop(this.scales.x)
......@@ -196,16 +203,16 @@
const y2 = d3.axisLeft(this.scales.y)
.tickSizeInner(this.padded.width)
.tickFormat('')
return { x1, x2, y1, y2 }
return {x1, x2, y1, y2}
},
regLine () {
const xValues = this.tmpResults.data.map(d => d.value_x)
const minX = d3.min(xValues)
const maxX = d3.max(xValues)
let x1 = this.scales.x(minX)
let y1 = this.scales.y(this.tmpResults.intercept + this.tmpResults.slope * minX)
let x2 = this.scales.x(maxX)
let y2 = this.scales.y(this.tmpResults.intercept + this.tmpResults.slope * maxX)
let x1 = this.scales.x(minX) || 0
let y1 = this.scales.y(this.tmpResults.intercept + this.tmpResults.slope * minX) || 0
let x2 = this.scales.x(maxX) || 0
let y2 = this.scales.y(this.tmpResults.intercept + this.tmpResults.slope * maxX) || 0
x1 = x1 < 0 ? 0 : x1
x1 = x1 > this.width ? this.width : x1
......@@ -225,7 +232,7 @@
<p>Intercept: ${this.tmpResults.intercept}</p>
</div>
`
return { x1, x2, y1, y2, tooltip }
return {x1, x2, y1, y2, tooltip}
},
brush () {
return d3.brush()
......@@ -251,7 +258,7 @@
this.hasSetFilter = true
})
},
histograms () {
histogramBins () {
const BINS = 14
let xBins = []
let yBins = []
......@@ -271,11 +278,11 @@
.domain([yMin, yMax])
.thresholds(yThresholds)(yValues)
}
return { xBins, yBins }
return {xBins, yBins}
},
histogramScales () {
const xExtent = d3.extent(this.histograms.xBins.map(d => d.length))
const yExtent = d3.extent(this.histograms.yBins.map(d => d.length))
const xExtent = d3.extent(this.histogramBins.xBins.map(d => d.length))
const yExtent = d3.extent(this.histogramBins.yBins.map(d => d.length))
// no, I didn't mix up x and y.
const x = d3.scaleLinear()
.domain(yExtent)
......@@ -283,21 +290,25 @@
const y = d3.scaleLinear()
.domain(xExtent)
.range([xExtent[0] ? 10 : 0, this.margin.bottom])
return { x, y }
return {x, y}
},
histPolyPoints () {
const bottom = this.histograms.xBins.map(d => {
return `${this.scales.x(d.x0)},${this.padded.height + 1}, ` +
`${this.scales.x(d.x0)},${this.padded.height + this.histogramScales.y(d.length) + 1} ` +
`${this.scales.x(d.x1)},${this.padded.height + this.histogramScales.y(d.length) + 1} ` +
`${this.scales.x(d.x1)},${this.padded.height + 1}`
}).join(' ')
const left = this.histograms.yBins.map(d => {
return `${0},${this.scales.y(d.x0)} ` +
`${-this.histogramScales.x(d.length)},${this.scales.y(d.x0)} ` +
`${-this.histogramScales.x(d.length)},${this.scales.y(d.x1)} ` +
`${0},${this.scales.y(d.x1)}`
}).join(' ')
histogram () {
const bottom = this.histogramBins.xBins.map(d => {
return {
x: this.scales.x(d.x0),
y: this.padded.height,
width: this.scales.x(d.x1) - this.scales.x(d.x0),
height: this.histogramScales.y(d.length)
}
})
const left = this.histogramBins.yBins.map(d => {
return {
x: -this.histogramScales.x(d.length),
y: this.scales.y(d.x0),
width: this.histogramScales.x(d.length),
height: this.scales.y(d.x0) - this.scales.y(d.x1)
}
})
return { bottom, left }
}
},
......@@ -305,26 +316,6 @@
// statement. This helps with the integration into the Vue component lifecycle. E.g.: an animation can't be
// applied to an element that does not exist yet.
watch: {
'regLine': {
handler: function (newRegLine) {
TweenLite.to(this.tweened.regLine, store.getters.animation ? 0.5 : 0, newRegLine)
}
},
'histPolyPoints': {
handler: function (newPoints) {
this.$nextTick(() => {
// we use d3 instead of TweenLite here because d3 can transition point paths
d3.select(this.$el.querySelector('.fjs-histogram-polyline.fjs-bottom'))
.transition()
.duration(store.getters.animation ? 500 : 0)
.attr('points', newPoints.bottom)
d3.select(this.$el.querySelector('.fjs-histogram-polyline.fjs-left'))
.transition()
.duration(store.getters.animation ? 500 : 0)
.attr('points', newPoints.left)
})
}
},
'args': {
handler: function (newArgs, oldArgs) {
const init = newArgs.x !== oldArgs.x ||
......@@ -353,16 +344,6 @@
d3.select(this.$el.querySelector('.fjs-brush')).call(newBrush)
})
}
},
'points': {
handler: function (newPoints) {
tweenGroup({
mutation: (v) => { this.tweened.points = v },
model: this.tweened.points,
target: newPoints,
animationTime: 0.5
})
}
}
},
components: {
......@@ -421,7 +402,7 @@
stroke-width: 0.3%
.fjs-lin-reg-line:hover
opacity: 0.4
.fjs-histogram-polyline
.fjs-histogram
shape-rendering: crispEdges
stroke: #fff
stroke-width: 1px
......
......@@ -53,9 +53,9 @@
:fill="categoryColors[categories.indexOf(point.category) % categoryColors.length]"
:title="point.tooltip"
v-tooltip
v-for="point in tweened.points">
v-for="point in points">
</polygon>
<g v-for="loading in tweened.loadings">
<g v-for="loading in loadings">
<line class="fjs-loadings"
:x1="loading.x1"
:x2="loading.x2"
......@@ -68,20 +68,20 @@
text-anchor="middle">
{{ loading.feature }}
</text>
<g class="fjs-pc-distribution" :transform="`translate(0, ${padded.height + margin.bottom / 2})`">
<line x1="0" y1="0" :x2="padded.width" y2="0"></line>
<g class="fjs-pc-distribution fjs-pc-x-distribution"
:transform="`translate(0, ${padded.height + margin.bottom / 2})`">
<line :x2="padded.width"></line>
<circle :cx="point.x"
cy="0"
:r="width / 150"
v-for="point in tweened.points">
v-for="point in points">
</circle>
</g>
<g class="fjs-pc-distribution" :transform="`translate(${- margin.left / 2}, 0)`">
<line x1="0" y1="0" x2="0" :y2="padded.height"></line>
<circle cx="0"
:cy="point.y"
<g class="fjs-pc-distribution fjs-pc-y-distribution"
:transform="`translate(${- margin.left / 2}, 0)`">
<line :y2="padded.height"></line>
<circle :cy="point.y"
:r="width / 150"
v-for="point in tweened.points">
v-for="point in points">
</circle>
</g>
</g>
......@@ -95,7 +95,7 @@
import DataBox from '../components/DataBox.vue'
import ControlPanel from '../components/ControlPanel.vue'
import Chart from '../components/Chart.vue'
import { getPolygonPointsForSubset, tweenGroup } from '../mixins/utils'
import { getPolygonPointsForSubset } from '../mixins/utils'
import store from '../../store/store'
import runAnalysis from '../mixins/run-analysis'
import * as d3 from 'd3'
......@@ -129,10 +129,6 @@
categoryColors: d3.schemeCategory10,
subsetColors: d3.schemeCategory10.slice().reverse(),
selectedPoints: [],
tweened: {
points: [],
loadings: []
},
hasSetFilter: false,
params: {
whiten: false
......@@ -286,26 +282,6 @@
})
}
},
'points': {
handler: function (newPoints) {
tweenGroup({
mutation: (v) => { this.tweened.points = v },
model: this.tweened.points,
target: newPoints,
animationTime: 0.5
})
}
},
'loadings': {
handler: function (newLoadings) {
tweenGroup({
mutation: (v) => { this.tweened.loadings = v },
model: this.tweened.loadings,
target: newLoadings,
animationTime: 0.5
})
}
},
'brush': {
handler: function (newBrush) {
this.$nextTick(() => {
......
......@@ -9,10 +9,6 @@
<i class="fjs-lock-btn material-icons" @click="toggleLock">{{ lockIcon }}</i>
</div>
<span class="fjs-panel-label" v-show="!shown">Control Panel</span>
<div>
<input id="fjs-animation-check" type="checkbox" @click="toggleAnimation" checked/>
<label for="fjs-animation-check">Animations Enabled</label>
</div>
<div v-show="shown">
<slot></slot>
<hr class="fjs-seperator"/>
......@@ -54,17 +50,12 @@
this.locked = !this.locked
this.propagateState()
},
toggleAnimation (event) {
store.dispatch('setAnimation', event.target.checked)
},
show (animate) {
animate = typeof animate === 'undefined' ? true : animate
show () {
this.expanded = true
this.propagateState()
this.shown = true
},
hide (animate) {
animate = typeof animate === 'undefined' ? true : animate
hide () {