https://codepen.io/callumacrae/pen/oyXXWR
Vue.js and SVG@callumacrae
View Slide
Hi, I’m Callum @callumacraeThings I love:• SVG• Animation• Vue.js
Building a bar chart@callumacrae
Building a bar chartconst randomData = () => new Array(6).fill('').map(() => 1 + Math.floor(Math.random() * 20));new Vue({el: '#chart',data: {chartData: randomData(),}});@callumacrae
Building a bar chartnew Vue({el: '#chart',data: {chartData: randomData(),}});v-for="value in chartData"class="bar":style="{ height: '60px', width: `${value * 30}px` }">@callumacrae
Building a bar chartnew Vue({el: '#chart',data: {chartData: randomData(),}});v-for="(value, i) in chartData"x="0" :y="i * 70"height="60" :width="value * 30">@callumacrae
Building a bar chartnew Vue({el: '#chart',data: {chartData: randomData(),}});v-for="(value, i) in chartData"x="0" :y="i * 70"height="60" :width="value * 30">#chart rect {fill: hsl(10, 80%, 70%);}@callumacrae
Building a bar chartnew Vue({el: '#chart',data: {chartData: randomData(),}});v-for="(value, i) in chartData"x="0" :y="i * 70"height="60" :width="value * 30"fill="hsl(10, 80%, 70%)">#chart rect {fill: hsl(10, 80%, 70%);}@callumacrae
Building a bar chartv-for="(value, i) in chartData"x="0" :y="i * 70"height="60" :width="value * 30">@callumacrae
Building a bar chartv-for="(value, i) in chartData"x="0" :y="i * 70"height="60" :width="value * 30">v-for="(value, i) in chartData":transform="`translate(0, ${i * 70})`">@callumacrae
Building a bar chartv-for="(value, i) in chartData":transform="`translate(0, ${i * 70})`">@callumacrae
Building a bar chartv-for="(value, i) in chartData":transform="`translate(0, ${i * 70})`">{{ value }}@callumacrae
Building a bar chartv-for="(value, i) in chartData":transform="`translate(0, ${i * 70})`">{{ value }}#chart text {fill: white;font: 20px sans-serif;text-anchor: end;alignment-baseline: middle;}@callumacrae
/rect>lue }}#chart text {fill: white;font: 20px sans-serif;text-anchor: end;alignment-baseline: middle;}SVG text positioningtext-anchor: start;Text@callumacrae
/rect>lue }}#chart text {fill: white;font: 20px sans-serif;text-anchor: end;alignment-baseline: middle;}SVG text positioningtext-anchor: middle;Text
/rect>lue }}#chart text {fill: white;font: 20px sans-serif;text-anchor: end;alignment-baseline: middle;}SVG text positioningtext-anchor: end;Text
#chart text {fill: white;font: 20px sans-serif;text-anchor: end;alignment-baseline: middle;}SVG text positioningalignment-baseline: baseline;Text/rect>lue }}
/rect>lue }}#chart text {fill: white;font: 20px sans-serif;text-anchor: end;alignment-baseline: middle;}SVG text positioningalignment-baseline: hanging;Text
/rect>lue }}#chart text {fill: white;font: 20px sans-serif;text-anchor: end;alignment-baseline: middle;}SVG text positioningalignment-baseline: middle;Text@callumacrae
#chart text {fill: white;font: 20px sans-serif;text-anchor: end;alignment-baseline: middle;}Building a bar chartv-for="(value, i) in chartData":transform="`translate(0, ${i * 70})`">{{ value }}@callumacrae
Animating a bar chart@callumacrae
No@callumacrae
Not really@callumacrae
Not really• We can use enter transitions to add new items• We can use list move transitions if the order were changing• Vue doesn't really help us transition state@callumacrae
@callumacrae
Animating a bar chartv-for="(value, i) in chartData":transform="`translate(0, ${i * 70})`">{{ value }}@callumacrae
Animating a bar chartv-for="(value, i) in chartData":transform="`translate(0, ${i * 70})`":value="value">Vue.component("animated-bar", {props: ["value"],template: `{{ value }}`,});@callumacrae
art="410">"* 70})`"lue * 30">- 10">{{ value }}Tweening with GSAPnew Vue({el: "#app",data: { number: 0 },mounted() {gsap.to(this.$data, { duration: 4, number: 1000 });},});@callumacrae
Animating a bar chartVue.component("animated-bar", {props: ["value"],template: `{{ value }}`,});@callumacrae
Animating a bar chartVue.component("animated-bar", {props: ["value"],template: `{{ value }}`,computed: {width() {return this.value * 30;},},});@callumacrae
Animating a bar chartVue.component("animated-bar", {props: ["value"],template: `{{ value }}`,data: () => ({ tweenedValue: 0 }),computed: {width() {return this.value * 30;},},});@callumacrae
Animating a bar chartVue.component("animated-bar", {props: ["value"],template: `{{ value }}`,data: () => ({ tweenedValue: 0 }),computed: {width() {return this.value * 30;},},watch: {value() {gsap.to(this.$data, { duration: 0.6, tweenedValue: this.value });},},}); @callumacrae
Animating a bar chartVue.component("animated-bar", {props: ["value"],template: `{{ value }}`,data: () => ({ tweenedValue: 0 }),computed: {width() {return this.tweenedValue * 30;},},watch: {value() {gsap.to(this.$data, { duration: 0.6, tweenedValue: this.value });},},}); @callumacrae
Vue.component("animated-bar", {props: ["value"],template: `{{ value }}`,data: () => ({ tweenedValue: 0 }),computed: {width() {return this.tweenedValue * 30;},},watch: {value() {gsap.to(this.$data, { duration: 0.6, tweenedValue: this.value });},},});Animating a bar chart@callumacrae
Vue.component("animated-bar", {props: ["value"],template: `{{ Math.round(tweenedValue) }}`,data: () => ({ tweenedValue: 0 }),computed: {width() {return this.tweenedValue * 30;},},watch: {value() {gsap.to(this.$data, { duration: 0.6, tweenedValue: this.value });},},});Animating a bar chart@callumacrae
So what else can we do?@callumacrae
https://www.reddit.com/r/dataisbeautiful/comments/fxe484/oc_rating_of_the_office_episodes_according_to/
https://www.reddit.com/r/dataisbeautiful/comments/fwy7dj/oc_the_remarkable_decline_in_child_mortality/
https://www.reddit.com/r/dataisbeautiful/comments/fqqzki/worst_episode_ever_the_most_commonly_rated_shows/
SVG paths - Vue?
SVG paths - Vue?https://medium.com/@mbostock/introducing-d3-shape-73f8367e6d12
SVG paths - d3!
SVG paths - d3!Vue.component("chart-line", {props: ["data"],template: ``,computed: {pathString() {return d3.line()(this.data);},},});:data="[[0, 50], [100, 80], [200, 40], [300, 60], [400, 30]]">
Thank you @callumacrae