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.

Categories
Vue and D3

Adding Graphics to a Vue App with D3 — Circle 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.

Circle Chart

We can add a circle into our Vue app with D3.

To do this, we write:

<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 = 400;
      const height = 400;
      const data = [10, 24, 35];
      const colors = ["green", "lightblue", "yellow"];

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

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

      g.append("circle")
        .attr("cx", function (d, i) {
          return i * 75 + 50;
        })
        .attr("cy", function (d, i) {
          return 75;
        })
        .attr("r", function (d) {
          return d * 1.5;
        })
        .attr("fill", function (d, i) {
          return colors[i];
        });

      g.append("text")
        .attr("x", function (d, i) {
          return i * 75 + 25;
        })
        .attr("y", 80)
        .attr("stroke", "teal")
        .attr("font-size", "10px")
        .attr("font-family", "sans-serif")
        .text(function (d) {
          return d;
        });
    });
  },
};
</script>

We start by creating the constants for the SVG with the width and height variables.

The data has the data we want to display.

colors have the color for each circle.

We use the width and height to create the SVG with:

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

Then we add the SVG group g with:

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

Then we add the circles with:

g.append("circle")
  .attr("cx", function(d, i) {
    return i * 75 + 50;
  })
  .attr("cy", function(d, i) {
    return 75;
  })
  .attr("r", function(d) {
    return d * 1.5;
  })
  .attr("fill", function(d, i) {
    return colors[i];
  });

We set the cx and cy attributes to add the x and y coordinates of the center of the circles.

Then we add the r attribute to add the radius. The radius is proportional to the number in data so if the number is bigger, the radius is bigger.

Then fill is an entry in the colors array.

Finally, we add the number display with:

g.append("text")
  .attr("x", function(d, i) {
    return i * 75 + 25;
  })
  .attr("y", 80)
  .attr("stroke", "teal")
  .attr("font-size", "10px")
  .attr("font-family", "sans-serif")
  .text(function(d) {
    return d;
  });

The text’s x and y attributes are the x and y coordinates of the position of the text.

stroke has the text color.

font-size is the size of the font. font-family is the font type.

text has a callback that returns the text to display.

Conclusion

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