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.

Categories
Vue and D3

Adding Graphics to a Vue App with D3 — Arrays, Collections, and Elements

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.

Arrays

D3 has methods to let us work with an array of numbers easily.

For example, we can write:

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

export default {
  name: "App",
  mounted() {
    const data = [20, 40, 60, 80, 100];
    console.log(d3.min(data));
    console.log(d3.max(data));
    console.log(d3.extent(data));
    console.log(d3.sum(data));
    console.log(d3.mean(data));
    console.log(d3.quantile(data, 0.5));
    console.log(d3.variance(data));
    console.log(d3.deviation(data));
  },
};
</script>

We get the min value of the array with the d3.min method.

The max can be obtained from the d3.max method.

d3.extent returns the min and max of the array.

d3.sum returns the sum of the array values.

d3.mean returns the average of the array values.

d3.quantile returns the given quantile.

d3.variance returns the variance from the data.

d3.deviation returns the standard deviation of the data.

Collections API

We also work with objects with D3.

For example, we can write:

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

export default {
  name: "App",
  mounted() {
    const month = { jan: 1, Feb: 2, mar: 3, apr: 4 };
    console.log(d3.keys(month));
    console.log(d3.values(month));
    console.log(d3.entries(month));
  },
};
</script>

to get the keys, values, and key-value pairs from the month object respectively.

Selection API

We can select elements from the DOM and then style it our way.

For example, we can write:

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

export default {
  name: "App",
  mounted() {
    d3.select("p").style("color", "red");
  },
};
</script>

select selects the first p element from the DOM.

Then we call style to set its color to red.

Also, we can write:

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

export default {
  name: "App",
  mounted() {
    d3.selectAll("body").style("color", "red");
  },
};
</script>

Then we select all the body elements.

We can chain the methods.

For example, we can write:

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

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

We get the belement in the p element by chaining the selectAll method.

Also, we can filter elements that are selected with the filter method:

For instance, we can write:

<template>
  <div id="app">
    <table>
      <tr>
        <td>foo</td>
      </tr>
      <tr>
        <td>bar</td>
      </tr>
      <tr>
        <td>baz</td>
      </tr>
    </table>
  </div>
</template>
<script>
import * as d3 from "d3";

export default {
  name: "App",
  mounted() {
    const even = d3.selectAll("tr").filter(":nth-child(odd)");
    console.log(even);
  },
};
</script>

to get all the tr elements with even indexes.

We can merge the selections with the merge method:

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

export default {
  name: "App",
  mounted() {
    Vue.nextTick(() => {
      const width = 300;
      const height = 300;
      const svg = d3
        .select("#svgcontainer")
        .append("svg")
        .attr("width", width)
        .attr("height", height);
      const rect = svg
        .append("rect")
        .attr("x", 20)
        .attr("y", 20)
        .attr("width", 200)
        .attr("height", 100)
        .attr("fill", "green");

      const rect2 = svg
        .append("rect")
        .attr("x", 20)
        .attr("y", 20)
        .attr("width", 100)
        .attr("height", 100)
        .attr("fill", "blue");

      rect.enter().append("rect").merge(rect2);
    });
  },
};
</script>

We have 2 rectangles, rect and rect2 .

Then we have:

rect.enter().append("rect").merge(rect2);

to combine the 2 rectangles together.

Now we see the blue and green rectangles side by side.

Conclusion

We can work with arrays, objects, and DOM elements with D3 in Vue apps.

Categories
Vue and D3

Adding Graphics to a Vue App with D3 — Line Graph

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.

Graphs

We can add graphs to our Vue app with D3.

For example, we can write:

public/data.csv

year,population
2006,20
2008,35
2010,48
2012,51
2014,63
2016,23
2017,42

App.vue

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

export default {
  name: "App",
  mounted() {
    Vue.nextTick(async () => {
      const margin = { top: 20, right: 20, bottom: 30, left: 50 },
        width = 960 - margin.left - margin.right,
        height = 500 - margin.top - margin.bottom;

      const x = d3.scaleTime().range([0, width]);
      const y = d3.scaleLinear().range([height, 0]);

      const valueline = d3
        .line()
        .x(function (d) {
          return x(d.year);
        })
        .y(function (d) {
          return y(d.population);
        });

      const svg = d3
        .select("body")
        .append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
        .append("g")
        .attr("transform", `translate(${margin.left}, ${margin.top})`);

      const data = await d3.csv("/data.csv");

      data.forEach(function (d) {
        d.population = +d.population;
      });

      x.domain(
        d3.extent(data, function (d) {
          return d.year;
        })
      );

      y.domain([
        0,
        d3.max(data, function (d) {
          return d.population;
        }),
      ]);

      svg
        .append("path")
        .data([data])
        .attr("class", "line")
        .attr("d", valueline);

      svg
        .append("g")
        .attr("transform", `translate(0, ${height})`)
        .call(d3.axisBottom(x));

      svg.append("g").call(d3.axisLeft(y));
    });
  },
};
</script>

<style>
.line {
  fill: none;
  stroke: green;
  stroke-width: 5px;
}
</style>

We have the data we read from in public/data.csv .

Then we create the graph by creating the constants for the width and height./

Then we add the x and y axes objects:

const margin = {
    top: 20,
    right: 20,
    bottom: 30,
    left: 50
  },
  width = 960 - margin.left - margin.right,
  height = 500 - margin.top - margin.bottom;

const x = d3.scaleTime().range([0, width]);
const y = d3.scaleLinear().range([height, 0]);

Then we create the line objects for the x and y axes by writing:

const valueline = d3
  .line()
  .x(function(d) {
    return x(d.year);
  })
  .y(function(d) {
    return y(d.population);
  });

Then we add the SVG into the body by writing:

const svg = d3
  .select("body")
  .append("svg")
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)
  .append("g")
  .attr("transform", `translate(${margin.left}, ${margin.top})`);

Then we read in the data that we want to display by writing:

const data = await d3.csv("/data.csv");

Next, we transform the read data by converting the population into numbers:

data.forEach(function(d) {
  d.population = +d.population;
});

Then we add callbacks to return the data for the x and y axes:

x.domain(
  d3.extent(data, function(d) {
    return d.year;
  })
);

y.domain([
  0,
  d3.max(data, function(d) {
    return d.population;
  }),
]);

Then we create the line for the line chart with:

svg
  .append("path")
  .data([data])
  .attr("class", "line")
  .attr("d", valueline);

Finally, we add the x and y axes with:

svg
   .append("g")
   .attr("transform", `translate(0, ${height})`)
   .call(d3.axisBottom(x));

svg.append("g").call(d3.axisLeft(y));

We have to add some styles to remove the width of the line and set the thickness of it:

<style>
.line {
  fill: none;
  stroke: green;
  stroke-width: 5px;
}
</style>

Now we should see a line graph displayed.

Conclusion

We can add a line graph with D3 into our Vue app.

Categories
Vue and D3

Adding Graphics to a Vue App with D3 — Pie Chart

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.

Pie Chart

We can add a pie chart with D3 into our Vue app.

For example, we can write:

public/populations.csv

states,percent
California,38.00
New York,18.00
Texas,20.0

App.vue

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

export default {
  name: "App",
  mounted() {
    Vue.nextTick(async () => {
      const svg = d3.select("svg"),
        width = svg.attr("width"),
        height = svg.attr("height"),
        radius = Math.min(width, height) / 2;

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

      const color = d3.scaleOrdinal(["gray", "green", "brown"]);

      const pie = d3.pie().value(function (d) {
        return d.percent;
      });

      const path = d3
        .arc()
        .outerRadius(radius - 10)
        .innerRadius(0);

      const label = d3
        .arc()
        .outerRadius(radius)
        .innerRadius(radius - 80);

      const data = await d3.csv("/populations.csv");

      const arc = g
        .selectAll(".arc")
        .data(pie(data))
        .enter()
        .append("g")
        .attr("class", "arc");

      arc
        .append("path")
        .attr("d", path)
        .attr("fill", function (d) {
          return color(d.data.states);
        });

      arc
        .append("text")
        .attr("transform", function (d) {
          return `translate(${label.centroid(d)})`;
        })
        .text(function (d) {
          return d.data.states;
        });

      svg
        .append("g")
        .attr("transform", `translate(${width / 2 - 120},20)`)
        .append("text")
        .text("Top population states in the US")
        .attr("class", "title");
    });
  },
};
</script>

<style scoped>
.arc text {
  font: 12px arial;
  text-anchor: middle;
}

.arc path {
  stroke: #fff;
}

.title {
  fill: green;
  font-weight: italic;
}
</style>

We start by getting the svg element and setting the width , height and radius of the pie chart:

const svg = d3.select("svg"),
  width = svg.attr("width"),
  height = svg.attr("height"),
  radius = Math.min(width, height) / 2;

Then we translate the svg by writing:

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

Next, we add the colors for the pie chart by writing;

const color = d3.scaleOrdinal(["gray", "green", "brown"]);

Then we add the data for the pie chunk by writing:

const pie = d3.pie().value(function(d) {
  return d.percent;
});

Next, we create the arcs for the pie chart by writing

const path = d3
  .arc()
  .outerRadius(radius - 10)
  .innerRadius(0);

Then we create the labels by writing:

const label = d3
  .arc()
  .outerRadius(radius)
  .innerRadius(radius - 80);

Then we read the data from populations.csv :

const data = await d3.csv("/populations.csv");

Then we set the lengths of the arcs with the read data by writing:

const arc = g
  .selectAll(".arc")
  .data(pie(data))
  .enter()
  .append("g")
  .attr("class", "arc");

Then we set the fill color of the pie chunks by writing:

arc
  .append("path")
  .attr("d", path)
  .attr("fill", function(d) {
    return color(d.data.states);
  });

Then we add the text for the pie chunks by writing:

arc
  .append("text")
  .attr("transform", function(d) {
    return `translate(${label.centroid(d)})`;
  })
  .text(function(d) {
    return d.data.states;
  });

And finally, we add the title text for the graph by writing:

svg
  .append("g")
  .attr("transform", `translate(${width / 2 - 120},20)`)
  .append("text")
  .text("Top population states in the US")
  .attr("class", "title");

Now we should see a pie chart displayed.

Conclusion

We can add a pie chart with D3 into our Vue app.