У меня есть два комбинированных графика (гистограмма и график площади) на холсте. Чего я хочу добиться, так это, если пользователь перемещает ползунок, график площади меняется в зависимости от этого. На данный момент мои значения хранятся в базе данных Firebase, но я думаю вместо этого жестко их кодировать. Значения ползунка - это, в основном, долларовые значения, которые будут умножаться на постоянный заряд и затем делиться на значение, введенное пользователем. Таким образом, пользователь может переместить ползунок к различным значениям в долларах, которые изменяют график площади.
Мне уже удалось заставить работать оба графика, но я действительно не представляю, как и где будет работать слайдер, поскольку я никогда раньше не работал с ними. На данный момент у меня есть следующее изображение:
Ссылка на изображение
// select the svg container first
const svg = d3.select('.canvas')
.append('svg')
.attr('width', 500)
.attr('height', 500);
// create margins & dimensions
const margin = {
top: 20,
right: 20,
bottom: 100,
left: 100
};
const graphWidth = 500 - margin.left - margin.right;
const graphHeight = 500 - margin.top - margin.bottom;
const graph = svg.append('g')
.attr('width', graphWidth)
.attr('height', graphHeight)
.attr('transform', `translate(${margin.left}, ${margin.top})`);
// create axes groups
const xAxisGroup = graph.append('g')
.attr('transform', `translate(0, ${graphHeight})`)
xAxisGroup.selectAll('text')
.attr('fill', '#19b393')
.attr('transform', 'rotate(-40)')
.attr('text-anchor', 'end');
const yAxisGroup = graph.append('g');
const y = d3.scaleLinear()
.range([graphHeight, 0]);
const x = d3.scaleBand()
.range([0, graphWidth])
.paddingInner(0.2)
.paddingOuter(0.1);
// create & call axes
const xAxis = d3.axisBottom(x)
.ticks(6);
const yAxis = d3.axisLeft(y)
.ticks(3)
.tickFormat(d => d + ' kWh');
const t = d3.transition().duration(1000);
const line = d3.area()
.x(function(d) {
return x(d.month_name)
})
.y1(function(d) {
return y(d.power_production)
})
.y0(y(0))
const path = graph.append('path');
// the update function
const update = (data) => {
// join the data to circs
const rects = graph.selectAll('rect')
.data(data)
const area = graph.selectAll('path')
rects.exit().remove();
// update the domains
y.domain([0, d3.max(data, d => d.power_production)]);
x.domain(data.map(item => item.month_name));
area.attr('fill', '#dcdcdc')
.attr('stroke', '#d3d3d3')
.attr('stroke-width', 2)
.attr('d', line(data));
rects.enter()
.append('rect')
.attr('width', x.bandwidth)
.attr("height", d => 0)
.attr('fill', '#19b393')
.attr('x', (d) => x(d.month_name))
.attr('y', d => graphHeight)
.merge(rects)
.transition(t)
.attr("height", d => graphHeight - y(d.ac_out))
.attr('y', d => y(d.ac_out));
xAxisGroup.call(xAxis);
yAxisGroup.call(yAxis);
};
var data = [];
var ref = '/test1/CafX0cm7FTSaIlT5WcfY/monthly_data/';
db.collection(ref).onSnapshot(res => {
res.docChanges().forEach(change => {
const doc = { ...change.doc.data(),
id: change.doc.id
};
switch (change.type) {
case 'added':
data.push(doc);
break;
case 'modified':
const index = data.findIndex(item => item.id == doc.id);
data[index] = doc;
break;
case 'removed':
data = data.filter(item => item.id !== doc.id);
break;
default:
break;
}
});
update(data);
});
Следующее изображение - это то, чего я хочу добиться для взаимодействия с пользователем: Ссылка на выходное изображение
Единственный график, который нужно изменить, это график области, гистограмма остается постоянной.