Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Vue.js and SVG

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on.

Vue.js and SVG

Avatar for Callum Macrae

Callum Macrae

April 09, 2020
Tweet

More Decks by Callum Macrae

Other Decks in Technology

Transcript

  1. 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
  2. Building a bar chart new Vue({ el: '#chart', data: {

    chartData: randomData(), } }); <div id="chart"> <div v-for="value in chartData" class="bar" :style="{ height: '60px', width: `${value * 30}px` }" ></div> </div> @callumacrae
  3. Building a bar chart new Vue({ el: '#chart', data: {

    chartData: randomData(), } }); <div id="chart"> <div v-for="value in chartData" class="bar" :style="{ height: '60px', width: `${value * 30}px` }" ></div> </div> @callumacrae
  4. Building a bar chart new Vue({ el: '#chart', data: {

    chartData: randomData(), } }); <svg id="chart" width="600" height="410"> <rect v-for="(value, i) in chartData" x="0" :y="i * 70" height="60" :width="value * 30" ></rect> </svg> @callumacrae
  5. Building a bar chart new Vue({ el: '#chart', data: {

    chartData: randomData(), } }); <svg id="chart" width="600" height="410"> <rect v-for="(value, i) in chartData" x="0" :y="i * 70" height="60" :width="value * 30" ></rect> </svg> @callumacrae
  6. Building a bar chart new Vue({ el: '#chart', data: {

    chartData: randomData(), } }); <svg id="chart" width="600" height="410"> <rect v-for="(value, i) in chartData" x="0" :y="i * 70" height="60" :width="value * 30" ></rect> </svg> #chart rect { fill: hsl(10, 80%, 70%); } @callumacrae
  7. Building a bar chart new Vue({ el: '#chart', data: {

    chartData: randomData(), } }); <svg id="chart" width="600" height="410"> <rect v-for="(value, i) in chartData" x="0" :y="i * 70" height="60" :width="value * 30" fill="hsl(10, 80%, 70%)" ></rect> </svg> #chart rect { fill: hsl(10, 80%, 70%); } @callumacrae
  8. Building a bar chart <svg id="chart" width="600" height="410"> <rect v-for="(value,

    i) in chartData" x="0" :y="i * 70" height="60" :width="value * 30" ></rect> </svg> @callumacrae
  9. Building a bar chart <svg id="chart" width="600" height="410"> <rect v-for="(value,

    i) in chartData" x="0" :y="i * 70" height="60" :width="value * 30" ></rect> </svg> <svg id="chart" width="600" height="410"> <g v-for="(value, i) in chartData" :transform="`translate(0, ${i * 70})`"> <rect height="60" :width="value * 30"></rect> </g> </svg> @callumacrae
  10. Building a bar chart <svg id="chart" width="600" height="410"> <g v-for="(value,

    i) in chartData" :transform="`translate(0, ${i * 70})`"> <rect height="60" :width="value * 30"></rect> </g> </svg> @callumacrae
  11. Building a bar chart <svg id="chart" width="600" height="410"> <g v-for="(value,

    i) in chartData" :transform="`translate(0, ${i * 70})`"> <rect height="60" :width="value * 30"></rect> <text y="30" :x="value * 30 - 10">{{ value }}</text> </g> </svg> @callumacrae
  12. Building a bar chart <svg id="chart" width="600" height="410"> <g v-for="(value,

    i) in chartData" :transform="`translate(0, ${i * 70})`"> <rect height="60" :width="value * 30"></rect> <text y="30" :x="value * 30 - 10">{{ value }}</text> </g> </svg> @callumacrae
  13. Building a bar chart <svg id="chart" width="600" height="410"> <g v-for="(value,

    i) in chartData" :transform="`translate(0, ${i * 70})`"> <rect height="60" :width="value * 30"></rect> <text y="30" :x="value * 30 - 10">{{ value }}</text> </g> </svg> #chart text { fill: white; font: 20px sans-serif; text-anchor: end; alignment-baseline: middle; } @callumacrae
  14. /rect> lue }}</text> #chart text { fill: white; font: 20px

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

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

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

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

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

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

    alignment-baseline: middle; } Building a bar chart <svg id="chart" width="600" height="410"> <g v-for="(value, i) in chartData" :transform="`translate(0, ${i * 70})`"> <rect height="60" :width="value * 30"></rect> <text y="30" :x="value * 30 - 10">{{ value }}</text> </g> </svg> @callumacrae
  21. 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
  22. Animating a bar chart <svg id="chart" width="600" height="410"> <g v-for="(value,

    i) in chartData" :transform="`translate(0, ${i * 70})`"> <rect height="60" :width="value * 30"></rect> <text y="30" :x="value * 30 - 10">{{ value }}</text> </g> </svg> @callumacrae
  23. Animating a bar chart <svg id="chart" width="600" height="410"> <animated-bar v-for="(value,

    i) in chartData" :transform="`translate(0, ${i * 70})`" :value="value"></animated-bar> </svg> Vue.component("animated-bar", { props: ["value"], template: ` <g> <rect height="60" :width="value * 30"></rect> <text y="30" :x="value * 30 - 10">{{ value }}</text> </g> `, }); @callumacrae
  24. art ="410"> " * 70})`" lue * 30"></rect> - 10">{{

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

    value }}</text> Tweening with GSAP new Vue({ el: "#app", data: { number: 0 }, mounted() { gsap.to(this.$data, { duration: 4, number: 1000 }); }, }); @callumacrae
  26. Animating a bar chart <svg id="chart" width="600" height="410"> <animated-bar v-for="(value,

    i) in chartData" :transform="`translate(0, ${i * 70})`" :value="value"></animated-bar> </svg> Vue.component("animated-bar", { props: ["value"], template: ` <g> <rect height="60" :width="value * 30"></rect> <text y="30" :x="value * 30 - 10">{{ value }}</text> </g> `, }); @callumacrae
  27. Animating a bar chart Vue.component("animated-bar", { props: ["value"], template: `

    <g> <rect height="60" :width="value * 30"></rect> <text y="30" :x="value * 30 - 10">{{ value }}</text> </g> `, }); @callumacrae
  28. Animating a bar chart Vue.component("animated-bar", { props: ["value"], template: `

    <g> <rect height="60" :width="value * 30"></rect> <text y="30" :x="value * 30 - 10">{{ value }}</text> </g> `, computed: { width() { return this.value * 30; }, }, }); @callumacrae
  29. Animating a bar chart Vue.component("animated-bar", { props: ["value"], template: `

    <g> <rect height="60" :width="width"></rect> <text y="30" :x="width - 10">{{ value }}</text> </g> `, computed: { width() { return this.value * 30; }, }, }); @callumacrae
  30. Animating a bar chart Vue.component("animated-bar", { props: ["value"], template: `

    <g> <rect height="60" :width="width"></rect> <text y="30" :x="width - 10">{{ value }}</text> </g> `, data: () => ({ tweenedValue: 0 }), computed: { width() { return this.value * 30; }, }, }); @callumacrae
  31. Animating a bar chart Vue.component("animated-bar", { props: ["value"], template: `

    <g> <rect height="60" :width="width"></rect> <text y="30" :x="width - 10">{{ value }}</text> </g> `, data: () => ({ tweenedValue: 0 }), computed: { width() { return this.value * 30; }, }, watch: { value() { gsap.to(this.$data, { duration: 0.6, tweenedValue: this.value }); }, }, }); @callumacrae
  32. Animating a bar chart Vue.component("animated-bar", { props: ["value"], template: `

    <g> <rect height="60" :width="width"></rect> <text y="30" :x="width - 10">{{ value }}</text> </g> `, data: () => ({ tweenedValue: 0 }), computed: { width() { return this.tweenedValue * 30; }, }, watch: { value() { gsap.to(this.$data, { duration: 0.6, tweenedValue: this.value }); }, }, }); @callumacrae
  33. Vue.component("animated-bar", { props: ["value"], template: ` <g> <rect height="60" :width="width"></rect>

    <text y="30" :x="width - 10">{{ value }}</text> </g> `, 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
  34. Vue.component("animated-bar", { props: ["value"], template: ` <g> <rect height="60" :width="width"></rect>

    <text y="30" :x="width - 10">{{ Math.round(tweenedValue) }}</text> </g> `, 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
  35. <path d="M 10,10 L 50,100 L 200,50 L 240,30 L

    300,60"></path> SVG paths - Vue?
  36. SVG paths - d3! Vue.component("chart-line", { props: ["data"], template: `<path

    :d="pathString"></path>`, computed: { pathString() { return d3.line()(this.data); }, }, }); <chart-line :data="[[0, 50], [100, 80], [200, 40], [300, 60], [400, 30]]" ></chart-line>
  37. SVG paths - d3! Vue.component("chart-line", { props: ["data"], template: `<path

    :d="pathString"></path>`, computed: { pathString() { return d3.line()(this.data); }, }, }); <chart-line :data="[[0, 50], [100, 80], [200, 40], [300, 60], [400, 30]]" ></chart-line>