$30 off During Our Annual Pro Sale. View Details »

Vue.js and SVG

Vue.js and SVG

Callum Macrae

April 09, 2020
Tweet

More Decks by Callum Macrae

Other Decks in Technology

Transcript

  1. Vue.js and SVG
    @callumacrae

    View Slide

  2. Hi, I’m Callum
    @callumacrae
    Things I love:

    • SVG

    • Animation

    • Vue.js

    View Slide

  3. Building a bar chart
    @callumacrae

    View Slide

  4. 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

    View Slide

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

    v-for="value in chartData"
    class="bar"
    :style="{ height: '60px', width: `${value * 30}px` }"
    >

    @callumacrae

    View Slide

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

    v-for="value in chartData"
    class="bar"
    :style="{ height: '60px', width: `${value * 30}px` }"
    >

    @callumacrae

    View Slide

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

    v-for="(value, i) in chartData"
    x="0" :y="i * 70"
    height="60" :width="value * 30"
    >

    @callumacrae

    View Slide

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

    v-for="(value, i) in chartData"
    x="0" :y="i * 70"
    height="60" :width="value * 30"
    >

    @callumacrae

    View Slide

  9. Building a bar chart
    new 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

    View Slide

  10. Building a bar chart
    new 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

    View Slide

  11. Building a bar chart
    @callumacrae

    View Slide

  12. Building a bar chart

    v-for="(value, i) in chartData"
    x="0" :y="i * 70"
    height="60" :width="value * 30"
    >

    @callumacrae

    View Slide

  13. Building a bar chart

    v-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

    View Slide

  14. Building a bar chart

    v-for="(value, i) in chartData"
    :transform="`translate(0, ${i * 70})`">



    @callumacrae

    View Slide

  15. Building a bar chart

    v-for="(value, i) in chartData"
    :transform="`translate(0, ${i * 70})`">

    {{ value }}


    @callumacrae

    View Slide

  16. Building a bar chart

    v-for="(value, i) in chartData"
    :transform="`translate(0, ${i * 70})`">

    {{ value }}


    @callumacrae

    View Slide

  17. Building a bar chart

    v-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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    v-for="(value, i) in chartData"
    :transform="`translate(0, ${i * 70})`">

    {{ value }}


    @callumacrae

    View Slide

  25. Animating a bar chart
    @callumacrae

    View Slide

  26. No
    @callumacrae

    View Slide

  27. Not really
    @callumacrae

    View Slide

  28. 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

    View Slide

  29. @callumacrae

    View Slide

  30. Animating a bar chart

    v-for="(value, i) in chartData"
    :transform="`translate(0, ${i * 70})`">

    {{ value }}


    @callumacrae

    View Slide

  31. Animating a bar chart

    v-for="(value, i) in chartData"
    :transform="`translate(0, ${i * 70})`"
    :value="value">

    Vue.component("animated-bar", {
    props: ["value"],
    template: `


    {{ value }}

    `,
    });
    @callumacrae

    View Slide

  32. 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

    View Slide

  33. 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

    View Slide

  34. Animating a bar chart

    v-for="(value, i) in chartData"
    :transform="`translate(0, ${i * 70})`"
    :value="value">

    Vue.component("animated-bar", {
    props: ["value"],
    template: `


    {{ value }}

    `,
    });
    @callumacrae

    View Slide

  35. Animating a bar chart
    Vue.component("animated-bar", {
    props: ["value"],
    template: `


    {{ value }}

    `,
    });
    @callumacrae

    View Slide

  36. Animating a bar chart
    Vue.component("animated-bar", {
    props: ["value"],
    template: `


    {{ value }}

    `,
    computed: {
    width() {
    return this.value * 30;
    },
    },
    });
    @callumacrae

    View Slide

  37. Animating a bar chart
    Vue.component("animated-bar", {
    props: ["value"],
    template: `


    {{ value }}

    `,
    computed: {
    width() {
    return this.value * 30;
    },
    },
    });
    @callumacrae

    View Slide

  38. Animating a bar chart
    Vue.component("animated-bar", {
    props: ["value"],
    template: `


    {{ value }}

    `,
    data: () => ({ tweenedValue: 0 }),
    computed: {
    width() {
    return this.value * 30;
    },
    },
    });
    @callumacrae

    View Slide

  39. 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

    View Slide

  40. 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

    View Slide

  41. 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

    View Slide

  42. 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

    View Slide

  43. So what else can we do?
    @callumacrae

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide


  47. SVG paths - Vue?

    View Slide

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

    View Slide

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

    View Slide

  50. SVG paths - d3!

    View Slide

  51. 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]]"
    >

    View Slide

  52. 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]]"
    >

    View Slide

  53. Thank you
    @callumacrae

    View Slide