Hi @jeffladiray,
So I tried to create a time-based (line chart) smart chart, but I wasn’t able to get it to work.
I used the example bar chart as a template, and here is what I have so far:
import Component from '@glimmer/component';
import { loadExternalStyle, loadExternalJavascript } from 'client/utils/smart-view-utils';
import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';
export default class extends Component {
constructor(...args) {
super(...args);
this.loadPlugin();
}
@tracked chart;
@tracked loaded = false;
async loadPlugin() {
await loadExternalJavascript('https://d3js.org/d3.v6.min.js');
this.loaded = true;
this.renderChart()
}
async fetchData() {
const response = await this.lianaServerFetch.fetch('/transactions');
const data = await response.json();
return data;
}
@action
async renderChart() {
if (!this.loaded) { return; }
const color = 'steelblue';
// Don't comment the lines below if you want to fetch data from your Forest server
// const usersData = await this.fetchData();
const data = await this.fetchData();
// const data = Object.assign(usersData.sort((a, b) => d3.descending(a.points, b.points)), {format: "%", y: "↑ Frequency"})
// const data =
// [{label: "15/11/21", value: 2},
// {label: "05/12/21", value: 1},
// {label: "14/12/21", value: 1},
// {label: "13/12/21", value: 1},
// {label: "12/12/21", value: 3}];
const height = 500;
const width = 800;
const margin = ({top: 30, right: 0, bottom: 30, left: 40})
const x = d3.scaleTime()
.domain(d3.range(data.length))
.range([margin.left, width - margin.right])
.padding(0.1)
const y = d3.scaleLinear()
.domain([0, d3.max(data, d => d.value)]).nice()
.range([height - margin.bottom, margin.top])
const valueline = d3
.line()
.x((d) => { return x(d.label); })
.y((d) => { return y(d.value); })
.curve(d3.curveCardinal);
const xAxis = g => g
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x).tickFormat(i => data[i].label).tickSizeOuter(0))
const yAxis = g => g
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(y).ticks(null, data.format))
.call(g => g.select(".domain").remove())
.call(g => g.append("text")
.attr("x", -margin.left)
.attr("y", 10)
.attr("fill", "currentColor")
.attr("text-anchor", "start")
.text("↑ Transactions")
.attr("dy", "1em"))
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height]);
svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.attr("fill", color);
// .data(data);
const linePath = svg
.append("path")
.data(data)
.attr("class", "line")
.attr("d", valueline)
const pathLength = linePath.node().getTotalLength();
linePath
.attr("stroke-dasharray", pathLength)
.attr("stroke-dashoffset", pathLength)
.attr("stroke-width", 3)
.attr("stroke-width", 0)
.attr("stroke-dashoffset", 0);
svg.append("g").call(xAxis);
svg.append("g").call(yAxis);
this.chart = svg.node();
}
}
Any ideas as to what I am doing wrong?
Thanks again!
Edit:
I found this tutorial very helpful:
“D3.js Line Chart Tutorial”