Slide 1

Slide 1 text

Vue.js and SVG @callumacrae

Slide 2

Slide 2 text

Hi, I’m Callum @callumacrae Things I love: • SVG • Animation • Vue.js

Slide 3

Slide 3 text

Building a bar chart @callumacrae

Slide 4

Slide 4 text

Building a bar chart const randomData = () => new Array(6).fill('') .map(() => 1 + Math.floor(Math.random() * 20)); new Vue({ el: '#chart', data: { chartData: randomData(), } }); @callumacrae

Slide 5

Slide 5 text

Building a bar chart new Vue({ el: '#chart', data: { chartData: randomData(), } });
@callumacrae

Slide 6

Slide 6 text

Building a bar chart new Vue({ el: '#chart', data: { chartData: randomData(), } });
@callumacrae

Slide 7

Slide 7 text

Building a bar chart new Vue({ el: '#chart', data: { chartData: randomData(), } }); @callumacrae

Slide 8

Slide 8 text

Building a bar chart new Vue({ el: '#chart', data: { chartData: randomData(), } }); @callumacrae

Slide 9

Slide 9 text

Building a bar chart new Vue({ el: '#chart', data: { chartData: randomData(), } }); #chart rect { fill: hsl(10, 80%, 70%); } @callumacrae

Slide 10

Slide 10 text

Building a bar chart new Vue({ el: '#chart', data: { chartData: randomData(), } }); #chart rect { fill: hsl(10, 80%, 70%); } @callumacrae

Slide 11

Slide 11 text

Building a bar chart @callumacrae

Slide 12

Slide 12 text

Building a bar chart @callumacrae

Slide 13

Slide 13 text

Building a bar chart @callumacrae

Slide 14

Slide 14 text

Building a bar chart @callumacrae

Slide 15

Slide 15 text

Building a bar chart {{ value }} @callumacrae

Slide 16

Slide 16 text

Building a bar chart {{ value }} @callumacrae

Slide 17

Slide 17 text

Building a bar chart {{ value }} #chart text { fill: white; font: 20px sans-serif; text-anchor: end; alignment-baseline: middle; } @callumacrae

Slide 18

Slide 18 text

/rect> lue }} #chart text { fill: white; font: 20px sans-serif; text-anchor: end; alignment-baseline: middle; } SVG text positioning text-anchor: start; Text @callumacrae

Slide 19

Slide 19 text

/rect> lue }} #chart text { fill: white; font: 20px sans-serif; text-anchor: end; alignment-baseline: middle; } SVG text positioning text-anchor: middle; Text

Slide 20

Slide 20 text

/rect> lue }} #chart text { fill: white; font: 20px sans-serif; text-anchor: end; alignment-baseline: middle; } SVG text positioning text-anchor: end; Text

Slide 21

Slide 21 text

#chart text { fill: white; font: 20px sans-serif; text-anchor: end; alignment-baseline: middle; } SVG text positioning alignment-baseline: baseline; Text /rect> lue }}

Slide 22

Slide 22 text

/rect> lue }} #chart text { fill: white; font: 20px sans-serif; text-anchor: end; alignment-baseline: middle; } SVG text positioning alignment-baseline: hanging; Text

Slide 23

Slide 23 text

/rect> lue }} #chart text { fill: white; font: 20px sans-serif; text-anchor: end; alignment-baseline: middle; } SVG text positioning alignment-baseline: middle; Text @callumacrae

Slide 24

Slide 24 text

#chart text { fill: white; font: 20px sans-serif; text-anchor: end; alignment-baseline: middle; } Building a bar chart {{ value }} @callumacrae

Slide 25

Slide 25 text

Animating a bar chart @callumacrae

Slide 26

Slide 26 text

No @callumacrae

Slide 27

Slide 27 text

Not really @callumacrae

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

@callumacrae

Slide 30

Slide 30 text

Animating a bar chart {{ value }} @callumacrae

Slide 31

Slide 31 text

Animating a bar chart Vue.component("animated-bar", { props: ["value"], template: ` {{ value }} `, }); @callumacrae

Slide 32

Slide 32 text

art ="410"> " * 70})`" lue * 30"> - 10">{{ value }} Tweening with GSAP new Vue({ el: "#app", data: { number: 0 }, mounted() { gsap.to(this.$data, { duration: 4, number: 1000 }); }, }); @callumacrae

Slide 33

Slide 33 text

art ="410"> " * 70})`" lue * 30"> - 10">{{ value }} Tweening with GSAP new Vue({ el: "#app", data: { number: 0 }, mounted() { gsap.to(this.$data, { duration: 4, number: 1000 }); }, }); @callumacrae

Slide 34

Slide 34 text

Animating a bar chart Vue.component("animated-bar", { props: ["value"], template: ` {{ value }} `, }); @callumacrae

Slide 35

Slide 35 text

Animating a bar chart Vue.component("animated-bar", { props: ["value"], template: ` {{ value }} `, }); @callumacrae

Slide 36

Slide 36 text

Animating a bar chart Vue.component("animated-bar", { props: ["value"], template: ` {{ value }} `, computed: { width() { return this.value * 30; }, }, }); @callumacrae

Slide 37

Slide 37 text

Animating a bar chart Vue.component("animated-bar", { props: ["value"], template: ` {{ value }} `, computed: { width() { return this.value * 30; }, }, }); @callumacrae

Slide 38

Slide 38 text

Animating a bar chart Vue.component("animated-bar", { props: ["value"], template: ` {{ value }} `, data: () => ({ tweenedValue: 0 }), computed: { width() { return this.value * 30; }, }, }); @callumacrae

Slide 39

Slide 39 text

Animating a bar chart Vue.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

Slide 40

Slide 40 text

Animating a bar chart 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 }); }, }, }); @callumacrae

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

So what else can we do? @callumacrae

Slide 44

Slide 44 text

https://www.reddit.com/r/dataisbeautiful/comments/fxe484/oc_rating_of_the_office_episodes_according_to/

Slide 45

Slide 45 text

https://www.reddit.com/r/dataisbeautiful/comments/fwy7dj/oc_the_remarkable_decline_in_child_mortality/

Slide 46

Slide 46 text

https://www.reddit.com/r/dataisbeautiful/comments/fqqzki/worst_episode_ever_the_most_commonly_rated_shows/

Slide 47

Slide 47 text

SVG paths - Vue?

Slide 48

Slide 48 text

SVG paths - Vue? https://medium.com/@mbostock/introducing-d3-shape-73f8367e6d12

Slide 49

Slide 49 text

SVG paths - Vue? https://medium.com/@mbostock/introducing-d3-shape-73f8367e6d12

Slide 50

Slide 50 text

SVG paths - d3!

Slide 51

Slide 51 text

SVG paths - d3! Vue.component("chart-line", { props: ["data"], template: ``, computed: { pathString() { return d3.line()(this.data); }, }, });

Slide 52

Slide 52 text

SVG paths - d3! Vue.component("chart-line", { props: ["data"], template: ``, computed: { pathString() { return d3.line()(this.data); }, }, });

Slide 53

Slide 53 text

Thank you @callumacrae