Categories
Vue and D3

Adding Graphics to a Vue App with D3 — CSV and TSV

D3 lets us add graphics to a front-end web app easily.

Vue is a popular front end web framework.

They work great together. In this article, we’ll look at how to add graphics to a Vue app with D3.

csvParseRows

We can use the csvParseRows method to parse CSV strings into rows.

For example, we can write:

<template>
  <div id="app"></div>
</template>
<script>
import * as d3 from "d3";
const string = `2011,10\n2012,20\n2013,30\n`;
export default {
  name: "App",
  mounted() {
    const data = d3.csvParseRows(string, function ([year, population]) {
      return {
        year: new Date(+year, 0, 1),
        population,
      };
    });
    console.log(data);
  },
};
</script>

We parse the CSV rows into an array with the csvParseRows method into a nested array.

The year and population are destructured from the parameter and we return them after parsing them.

csvFormat

We can use the csvFormat method to format the CSV rows and columns.

For example, we can write:

<template>
  <div id="app"></div>
</template>
<script>
import * as d3 from "d3";

const data = [
  { year: 2011, population: 10 },
  { year: 2012, population: 20 },
  { year: 2013, population: 30 },
];

export default {
  name: "App",
  mounted() {
    const string = d3.csvFormat(data, ["year", "population"]);
    console.log(string);
  },
};
</script>

We pass in an array of objects into the csvFormat method.

The 2nd argument is the column headings.

And then we get back:

year,population
2011,10
2012,20
2013,30

as the value of string .

tsvParse

We can use the tsvParse method to parse tab-separated strings.

For instance, we can write:

<template>
  <div id="app"></div>
</template>

<script>
import * as d3 from "d3";
const string = `yeartpopulation\n2011\t10\n2012\t20\n2013\t30\n`;

export default {
  name: "App",
  mounted() {
    const data = d3.tsvParse(string, function ({ year, population }) {
      return {
        year: new Date(+year, 0, 1),
        population,
      };
    });
    console.log(data);
  },
};
</script>

We have a string that has the columns separated by tabs.

And rows separated by a new line.

Then we call tsvParse to parse the string.

And we get the year and population in the parameter.

tsvParseRows

We can use the tsvParseRows to parse the rows in a tabbed separated string.

For example, we can write:

<template>
  <div id="app"></div>
</template>

<script>
import * as d3 from "d3";
const string = `2011\t10\n2012\t20\n2013\t30\n`;

export default {
  name: "App",
  mounted() {
    const data = d3.tsvParseRows(string, function ([year, population]) {
      return {
        year: new Date(+year, 0, 1),
        population,
      };
    });
    console.log(data);
  },
};
</script>

We parse the string and destructure the year and population from the parameter.

tsvFormat

We can call the tsvFormat method to convert an array of data to a tabbed separated string.

For instance, we can write:

<template>
  <div id="app"></div>
</template>

<script>
import * as d3 from "d3";
const data = [
  { year: 2011, population: 10 },
  { year: 2012, population: 20 },
  { year: 2013, population: 30 },
];
export default {
  name: "App",
  mounted() {
    const string = d3.tsvFormat(data, ["year", "population"]);
    console.log(string);
  },
};
</script>

We pass in the array in the first argument and an array of column names in the 2nd argument.

Then string is:

year population
2011 10
2012 20
2013 30

Conclusion

We can parse and create CSV and TSV files with D3 in a Vue app.

Categories
Vue and D3

Adding Graphics to a Vue App with D3 — Drag and Drop, Zoom, and CSV

D3 lets us add graphics to a front-end web app easily.

Vue is a popular front end web framework.

They work great together. In this article, we’ll look at how to add graphics to a Vue app with D3.

Drag and Drop

We can add drag and drop to our Vue app with D3 easily.

For example, we can write:

<template>
  <div id="app">
    <svg>
      <g>
        <rect x="40" y="10" width="50" height="50" fill="teal"></rect>
      </g>
    </svg>
  </div>
</template>
<script>
import * as d3 from "d3";
import Vue from "vue";

export default {
  name: "App",
  mounted() {
    Vue.nextTick(() => {
      d3.select("g")
        .datum({
          x: 0,
          y: 0,
        })
        .call(
          d3.drag().on("drag", function (d) {
            d3.select(this).attr("transform", `translate(${d.x} , ${d.y})`);
          })
        );
    });
  },
};
</script>

We have an SVG with a rectangle inside.

In the nextTick callback, we call d3.select to get the g element.

And then we call datum to set the x and y coordinates of the top left corner.

And then we call the call method by passing in the d3.drag().on method into the call method.

The callback gets the element we’re dragging with this .

And then we set the transform attribute to the drag position.

Zooming

We can add a zoom feature to shapes.

With it, we can use the mouse wheel to zoom in and out of an SVG.

For example, we can write:

<template>
  <div id="app">
    <div id="zoom"></div>
  </div>
</template>
<script>
import * as d3 from "d3";
import Vue from "vue";

export default {
  name: "App",
  mounted() {
    Vue.nextTick(() => {
      const svg = d3
        .select("#zoom")
        .append("svg")
        .attr("width", 460)
        .attr("height", 460)
        .call(
          d3.zoom().on("zoom", function (d) {
            svg.attr("transform", d.transform);
          })
        )
        .append("g");

      svg
        .append("circle")
        .attr("cx", 100)
        .attr("cy", 100)
        .attr("r", 40)
        .style("fill", "#68b2a1");
    });
  },
};
</script>

We have a div with ID zoom .

In the nextTick callback, we get the div and then add the svg element into it.

Then we call the call method with the d3.zoom method so that we can watch for zoom.

The d.transform has the string to change the size according to how much we zoom in or out.

Then we add the circle that we can zoom in and out.

cx and cy has the x and y coordinates of the center.

r has the radius.

style has the fill style.

Read Comma-Separated Values

We can read data from formatted data directly.

For example, we can write:

<template>
  <div id="app"></div>
</template>
<script>
import * as d3 from "d3";
const string = `year,population\n2011,10\n2012,20\n2013,30\n`;
export default {
  name: "App",
  mounted() {
    const data = d3.csvParse(string, function (d) {
      return {
        year: new Date(+d.year, 0, 1),
        population: d.population,
      };
    });
    console.log(data);
  },
};
</script>

to parse a CSV string with d3.csvParse .

The callback lets us return the transformed data after reading it.

d has the entry read and we return what we want as the new value of the entry.

Conclusion

We can add drag and drop, zooming, and read CSV strings with D3 in our Vue app.

Categories
Vue and D3

Adding Graphics to a Vue App with D3 — Colors and Transitions

D3 lets us add graphics to a front-end web app easily.

Vue is a popular front end web framework.

They work great together. In this article, we’ll look at how to add graphics to a Vue app with D3.

Colors

We can create color objects with the d3.color method.

For example, we can write:

<template>
  <div id="app"></div>
</template>
<script>
import * as d3 from "d3";

export default {
  name: "App",
  mounted() {
    const color = d3.color("green");
    console.log(color);
  },
};
</script>

to call d3.color .

Then color is:

{r: 0, g: 128, b: 0, opacity: 1}

We get the r, g, and b values and the opacity.

We get the same thing with the color.rgb() method:

<template>
  <div id="app"></div>
</template>
<script>
import * as d3 from "d3";

export default {
  name: "App",
  mounted() {
    const color = d3.color("green");
    console.log(color.rgb());
  },
};
</script>

The color object also has the toString method:

<template>
  <div id="app"></div>
</template>
<script>
import * as d3 from "d3";

export default {
  name: "App",
  mounted() {
    const color = d3.color("green");
    console.log(color.toString());
  },
};
</script>

We see:

rgb(0, 128, 0)

logged.

D3 also comes with the d3.rgb method to create an object with the RGB values:

<template>
  <div id="app"></div>
</template>
<script>
import * as d3 from "d3";

export default {
  name: "App",
  mounted() {
    console.log(d3.rgb("yellow"));
    console.log(d3.rgb(200, 100, 0));
  },
};
</script>

And we get:

{r: 255, g: 255, b: 0, opacity: 1}
{r: 200, g: 100, b: 0, opacity: 1}

The d3.hsl method creates a new HSL color:

<template>
  <div id="app"></div>
</template>
<script>
import * as d3 from "d3";

export default {
  name: "App",
  mounted() {
    const hsl = d3.hsl("blue");
    console.log((hsl.h += 100));
    console.log((hsl.opacity = 0.5));
  },
};
</script>

d3.lab creates a new lab color:

<template>
  <div id="app"></div>
</template>
<script>
import * as d3 from "d3";

export default {
  name: "App",
  mounted() {
    const lab = d3.lab("blue");
    console.log(lab);
  },
};
</script>

Then we get:

{l: 29.567572863553245, a: 68.29865326565671, b: -112.02942991288025, opacity: 1}

logged.

The d3.hcl method creates a new HCL color.

For example, we can write:

<template>
  <div id="app"></div>
</template>
<script>
import * as d3 from "d3";

export default {
  name: "App",
  mounted() {
    const hcl = d3.hcl("blue");
    console.log(hcl);
  },
};
</script>

d3.cubehelix creates a new Cubehelix color:

<template>
  <div id="app"></div>
</template>
<script>
import * as d3 from "d3";

export default {
  name: "App",
  mounted() {
    const cubehelix = d3.cubehelix("blue");
    console.log(cubehelix);
  },
};
</script>

And we get:

{h: 236.94217167732103, s: 4.614386868039719, l: 0.10999954957200976, opacity: 1}

Transitions

We can add transitions easily with D3 into our Vue app.

For example, we can write:

<template>
  <div id="app"></div>
</template>
<script>
import * as d3 from "d3";
import Vue from "vue";

export default {
  name: "App",
  mounted() {
    Vue.nextTick(() => {
      d3.selectAll("body")
        .transition()
        .style("background-color", "yellow")
        .transition()
        .delay(5000)
        .style("background-color", "blue")
        .delay(2000)
        .remove();
    });
  },
};
</script>

We call the transition method to create our transition.

Then we specify the styles to apply with the style method.

And we call delay to set the delay before the next transition is applied.

Conclusion

We can add colors and transitions with D3 into our Vue app.

Categories
Vue and D3

Adding Graphics to a Vue App with D3 — Axis and Arcs

D3 lets us add graphics to a front-end web app easily.

Vue is a popular front end web framework.

They work great together. In this article, we’ll look at how to add graphics to a Vue app with D3.

Axis API

We can use the axis API to add the axes for graphs.

For example, we can write:

<template>
  <div id="app"></div>
</template>
<script>
import * as d3 from "d3";
import Vue from "vue";

export default {
  name: "App",
  mounted() {
    Vue.nextTick(() => {
      const width = 400,
        height = 400;
      const data = [100, 120, 140, 160, 180, 200];
      const svg = d3
        .select("body")
        .append("svg")
        .attr("width", width)
        .attr("height", height);

      const xscale = d3
        .scaleLinear()
        .domain([0, d3.max(data)])
        .range([0, width - 100]);

      const yscale = d3
        .scaleLinear()
        .domain([0, d3.max(data)])
        .range([height / 2, 0]);

      const xAxis = d3.axisBottom().scale(xscale);
      const yAxis = d3.axisLeft().scale(yscale);
      svg.append("g").attr("transform", "translate(50, 10)").call(yAxis);
      const xAxisTranslate = height / 2 + 10;

      svg
        .append("g")
        .attr("transform", `translate(50, ${xAxisTranslate})`)
        .call(xAxis);
    });
  },
};
</script>

We add the value for the y-axis with the data array.

width and height has the width and height of the graph.

Then we create scale for the x-axis by writing:

const xscale = d3
  .scaleLinear()
  .domain([0, d3.max(data)])
  .range([0, width - 100]);

We create the scale for the y-axis with:

const yscale = d3
  .scaleLinear()
  .domain([0, d3.max(data)])
  .range([height / 2, 0]);

The axes show the values between the min and max value that we pass into domain .

We create the axes with:

const xAxis = d3.axisBottom().scale(xscale);
const yAxis = d3.axisLeft().scale(yscale);

Then we add the y-axis to the graph with:

svg.append("g").attr("transform", "translate(50, 10)").call(yAxis);

And we add the x-axis with:

svg
  .append("g")
  .attr("transform", `translate(50, ${xAxisTranslate})`)
  .call(xAxis);

Shapes

We can add shapes with D3 into our Vue app.

d3.arc generates an arc.

For example, we can write:

<template>
  <div id="app">
    <svg width="400" height="300"></svg>
  </div>
</template>
<script>
import * as d3 from "d3";
import Vue from "vue";

export default {
  name: "App",
  mounted() {
    Vue.nextTick(() => {
      const arc = d3.arc().innerRadius(50).outerRadius(40).cornerRadius(15);

      const svg = d3.select("svg"),
        width = +svg.attr("width"),
        height = +svg.attr("height"),
        g = svg
          .append("g")
          .attr("transform", `translate(${width / 2} , ${height / 2})`);

      const data = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89];
      const arcs = d3.pie()(data);
      g.selectAll("path")
        .data(arcs)
        .enter()
        .append("path")
        .style("fill", function (d, i) {
          return d3.color(`hsl(120, 50%, ${d.value}%)`);
        })
        .attr("d", arc);
    });
  },
};
</script>

to create an arc with the d3.arc function:

const arc = d3.arc().innerRadius(50).outerRadius(40).cornerRadius(15);

Then we get the dimensions from the SVG and create the arc group:

const svg = d3.select("svg"),
  width = +svg.attr("width"),
  height = +svg.attr("height"),
  g = svg
  .append("g")
  .attr("transform", `translate(${width / 2} , ${height / 2})`);

Then set create the data we want to display:

const data = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89];

Next, we load the data into the data.pie method to create the arcs for each segment of the pie:

const arcs = d3.pie()(data);

And finally, we show the arcs with the given colors by writing:

g.selectAll("path")
  .data(arcs)
  .enter()
  .append("path")
  .style("fill", function(d, i) {
    return d3.color(`hsl(120, 50%, ${d.value}%)`);
  })
  .attr("d", arc);

Conclusion

We can add axes and arcs with D3 into our Vue app.

Categories
Vue and D3

Adding Graphics to a Vue App with D3 — Selections and Scales

D3 lets us add graphics to a front-end web app easily.

Vue is a popular front end web framework.

They work great together. In this article, we’ll look at how to add graphics to a Vue app with D3.

Find Elements in Selections

We can find elements in selections.

For example, we can write:

<template>
  <div id="app">
    <div>
      <b>apple</b>
      <b>orange</b>
      <b>grape</b>
    </div>
  </div>
</template>
<script>
import * as d3 from "d3";
import Vue from "vue";

export default {
  name: "App",
  mounted() {
    Vue.nextTick(() => {
      let selection = d3.selectAll("b").filter(":nth-child(odd)").nodes();
      selection.forEach((e) => {
        console.log(e.textContent);
      });
    });
  },
};
</script>

to get all the b elements and filter them to get all the even index ones.

Then we call forEach to get their text content.

We can call the filter with the d3.matcher method.

For instance, we can write:

<template>
  <div id="app">
    <div></div>
    <div>
      <h5>This is text1</h5>
      <h5>This is text2</h5>
      <h5>This is text3</h5>
      <h5>This is text4</h5>
    </div>
  </div>
</template>
<script>
import * as d3 from "d3";
import Vue from "vue";

export default {
  name: "App",
  mounted() {
    Vue.nextTick(() => {
      const heading = d3.selectAll("h5");
      const matcher = heading.filter(d3.matcher("h5")).node();
      const filter = heading.filter(d3.matcher("h5")).node();
      console.log(matcher);
      console.log(filter);
    });
  },
};
</script>

to get the h5 elements with the matcher method to get the h5 element.

We can call d3.creator to create an element.

For instance, we can write:

<template>
  <div id="app"></div>
</template>
<script>
import * as d3 from "d3";
import Vue from "vue";

export default {
  name: "App",
  mounted() {
    Vue.nextTick(() => {
      const selection = d3.select("body");
      selection.append(d3.creator("div"));
      const div = document.querySelector("div");
      div.innerText = "hello world.";
    });
  },
};
</script>

The d3.creator method creates a div.

Then we get the div with querySelector and set the innerText property to add text content to it.

Paths API

We can add a shape with the paths API.

For example, we can write:

<template>
  <div id="app">
    <svg width="600" height="100">
      <path transform="translate(20, 0)" />
    </svg>
  </div>
</template>
<script>
import * as d3 from "d3";
import Vue from "vue";

export default {
  name: "App",
  mounted() {
    Vue.nextTick(() => {
      const data = [
        [0, 12],
        [50, 20],
        [100, 30],
        [200, 40],
        [300, 90],
      ];
      const lineGenerator = d3.line();
      const pathString = lineGenerator(data);
      d3.select("path").attr("d", pathString);
    });
  },
};
</script>

<style>
path {
  fill: green;
  stroke: #aaa;
}
</style>

We create the svg element.

Then we create the line with the d3.line method.

And then we pass in the data into the returned lineGenerator function.

Then we pass in the returned pathString into the attr method so set the SVG’s path.

Scales API

We can use the scales API to transform data in various ways.

For example, we can write:

<template>
  <div id="app"></div>
</template>
<script>
import * as d3 from "d3";
import Vue from "vue";

export default {
  name: "App",
  mounted() {
    Vue.nextTick(() => {
      const data = [100, 220, 330, 350, 400, 250];
      const width = 500,
        barHeight = 20,
        margin = 1;

      const scale = d3
        .scaleLinear()
        .domain([d3.min(data), d3.max(data)])
        .range([100, 400]);

     const svg = d3
        .select("body")
        .append("svg")
        .attr("width", width)
        .attr("height", barHeight * data.length);

     const g = svg
        .selectAll("g")
        .data(data)
        .enter()
        .append("g")
        .attr("transform", function (d, i) {
          return `translate(0, ${i * barHeight})`;
        });

      g.append("rect")
        .attr("width", function (d) {
          return scale(d);
        })
        .attr("height", barHeight - margin);

      g.append("text")
        .attr("x", function (d) {
          return scale(d);
        })
        .attr("y", barHeight / 2)
        .attr("dy", ".35em")
        .text(function (d) {
          return d;
        });
    });
  },
};
</script>

We have the data to display as bars.

And we have the width for the chart’s width.

barHeight has the bars’ height.

We create the scale object to scale the bars with:

const scale = d3
  .scaleLinear()
  .domain([d3.min(data), d3.max(data)])
  .range([100, 400]);

The scaleLinear method creates a continuous linear scale where we can map input data to the specified output range.

Then we add the SVG for the chart to the body with:

const svg = d3
  .select("body")
  .append("svg")
  .attr("width", width)
  .attr("height", barHeight * data.length);

Next, we add the bar group by writing:

const g = svg
  .selectAll("g")
  .data(data)
  .enter()
  .append("g")
  .attr("transform", function(d, i) {
    return `translate(0, ${i * barHeight})`;
  });

Then we set the widths of the bars by writing:

g.append("rect")
  .attr("width", function(d) {
    return scale(d);
  })
  .attr("height", barHeight - margin);

Then we set the bars to the length given by the data by writing:

g.append("text")
  .attr("x", function(d) {
    return scale(d);
  })
  .attr("y", barHeight / 2)
  .attr("dy", ".35em")
  .text(function(d) {
    return d;
  });

Conclusion

We can select items and create scales with D3.