gpt4 book ai didi

javascript - 将垂直线添加到 d3js 条形图

转载 作者:行者123 更新时间:2023-11-30 14:58:59 25 4
gpt4 key购买 nike

基于此example ,我正在尝试复制条形图。然后我有两个数据集:一个用于条形图,一个用于单一价格。

我想用那个单一价格做的是根据条形定位它。检查代码:

var price_data =  [
{'priceRangeStart':'4000000','numberOfProperties':100},
{'priceRangeStart':'4100000','numberOfProperties':256},
{'priceRangeStart':'4200000','numberOfProperties':773},
{'priceRangeStart':'4300000','numberOfProperties':334},
{'priceRangeStart':'4400000','numberOfProperties':587},
{'priceRangeStart':'4500000','numberOfProperties':400},
{'priceRangeStart':'4600000','numberOfProperties':700},
{'priceRangeStart':'4700000','numberOfProperties':150},
{'priceRangeStart':'4800000','numberOfProperties':229},
{'priceRangeStart':'4900000','numberOfProperties':500},
{'priceRangeStart':'5000000','numberOfProperties':125},
{'priceRangeStart':'5100000','numberOfProperties':170},
{'priceRangeStart':'5200000','numberOfProperties':290},
{'priceRangeStart':'5300000','numberOfProperties':660},
{'priceRangeStart':'5400000','numberOfProperties':450},
{'priceRangeStart':'5500000','numberOfProperties':359},
{'priceRangeStart':'5600000','numberOfProperties':740},
{'priceRangeStart':'5700000','numberOfProperties':894},
{'priceRangeStart':'5900000','numberOfProperties':547},
{'priceRangeStart':'6000000','numberOfProperties':1250}
];

var property_price = 5050000;


var loadPriceComparisonChart = function (data, single_price) {

// removing svg/tip artifacts
d3.selectAll('.price-comparison-tip').remove();
d3.select(elem[0]).select('svg').remove();

// variables and helpers
var margin = {top: 0, right: 20, bottom: 25, left: 0},
width = 370,
height = 200;

var formatComma = d3.format(',');


// responsive SVG
// create responsive svg container for the graph
var svg = d3.select(elem[0])
.append('div')
.classed('svg-price-comparison-container', true)
.append('svg')
.attr('preserveAspectRatio', 'none')
.attr('viewBox', '0 0 370 225')
//class to make it responsive
.classed('svg-content-responsive', true);

// creating x and y scales
var x = d3.scaleBand().rangeRound([0, width]).paddingOuter(0.5).paddingInner(0.6),
x1 = d3.scaleBand().rangeRound([0, width]),
y = d3.scaleLinear().rangeRound([height, 0]),
y1 = d3.scaleLinear().rangeRound([0, (height - 100)]); //

// creating the group object
var g = svg.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

// processing the data
var new_dataset = data;
var transformation = [];

transformation = new_dataset.map(el => (
{priceRangeStart: el.priceRangeStart, numberOfProperties: el.numberOfProperties}
));

transformation.forEach(function(d) {
d.priceRangeStart = +d.priceRangeStart;
d.numberOfProperties = +d.numberOfProperties;
return d;
});

// using lodash
var minValue = _.first(transformation).priceRangeStart;
var maxValue = _.last(transformation).priceRangeStart;

// get max number of properties value
var maxNrProperties = d3.max(transformation, function(d) {return d.numberOfProperties;});

// x and y value domains
x.domain(transformation.map(function(d) {console.log(d.priceRangeStart);return d.priceRangeStart;}));
x1.domain(transformation.map(function(d) {return d.priceRangeStart;}));
y.domain([0, ((d3.max(transformation, function(d) {return d.numberOfProperties;})) + (1.15 * maxNrProperties))]);
y1.domain([0, (d3.max(transformation, function(d) {return d.numberOfProperties;}))]);

// create x axis (for guiding purposes) and then hide it
g.append('g')
.attr('transform', 'translate(0,' + height + ')')
.attr('class', 'axis axis--x')
.call(d3.axisBottom(x))
.style('opacity', 0)
.selectAll('text').remove();

// text for min price value and translate it to the start position of the first bar
g.append('text')
.attr('transform', 'translate(' + (x(_.first(transformation).priceRangeStart)) + ' ,' + (height * 1.1) + ')')
.style('text-anchor', 'start')
.style('font-size', '12px')
.text('CHF ' + formatComma(minValue));

// text for max price value and translate it to the end position of the last bar
g.append('text')
.attr('transform', 'translate(' + (x(_.last(transformation).priceRangeStart) + x.bandwidth()) + ' ,' + (height * 1.1) + ')')
.style('text-anchor', 'end')
.style('font-size', '12px')
.text('CHF ' + formatComma(maxValue));

// apppend the grey bars to the graph and styling them
g.selectAll('.bar')
.data(transformation)
.enter().append('rect')
.attr('class', 'bar')
.attr('x', function(d) {return x(d.priceRangeStart);})
.attr('y', function(d) {return height - y1(maxNrProperties);})
.attr('width', x.bandwidth())
.attr('height', function(d) {return y1(maxNrProperties);})
.style('fill', '#A4A9AD')
.style('opacity', 0.2);

// apppend the orange bars to the graph and styling them
g.selectAll(null)
.data(transformation)
.enter().append('rect')
.attr('class', 'bar')
.attr('x', function(d) {return x(d.priceRangeStart);})
.attr('y', function(d) {return y(d.numberOfProperties);})
.attr('width', x.bandwidth())
.attr('height', function(d) {return height - y(d.numberOfProperties);})
.style('fill', '#EDAA00')
.style('opacity', 1);

// append dashed line to show single property price position
g.append('line')
.attr('class', 'zero')
.attr('x1', function(d) {return x1(single_price);})
.attr('y1', function(d) {return (y1(maxNrProperties) - 10);})
.attr('x2', x(0))
.attr('y2', function(d) {return height;})
.style('stroke', '#003A5D')
.style('stroke-width', 1)
.style('stroke-dasharray', 6)
.attr('transform', 'translate(30,0)');

如您所见,5050000 的单一价格应位于 5000000 和 5100000 范围内的柱形之间。该单一价格应该是垂直虚线而不是另一条柱形,如您在代码中看到的那样。问题是我无法正确定位它。由于某些原因,我无法使用为栏设置的 x 域。

最后,它应该看起来像这样: enter image description here有什么想法吗?

最佳答案

当您将这些值用作分类(定性)变量时,事情就变得复杂了。但是,有一个解决方案:

您可以使用 d3.bisectLeftx 标度域中获取低于该单一价格的值:

var lineIndex = d3.bisectLeft(x.domain(), property_price);

然后,使用该索引,获取该行的 x 位置:

.attr("x1", x(x.domain()[lineIndex]))
.attr("x2", x(x.domain()[lineIndex]))

这里是你的代码有那个变化:

var data = [{
'priceRangeStart': '4000000',
'numberOfProperties': 100
}, {
'priceRangeStart': '4100000',
'numberOfProperties': 256
}, {
'priceRangeStart': '4200000',
'numberOfProperties': 773
}, {
'priceRangeStart': '4300000',
'numberOfProperties': 334
}, {
'priceRangeStart': '4400000',
'numberOfProperties': 587
}, {
'priceRangeStart': '4500000',
'numberOfProperties': 400
}, {
'priceRangeStart': '4600000',
'numberOfProperties': 700
}, {
'priceRangeStart': '4700000',
'numberOfProperties': 150
}, {
'priceRangeStart': '4800000',
'numberOfProperties': 229
}, {
'priceRangeStart': '4900000',
'numberOfProperties': 500
}, {
'priceRangeStart': '5000000',
'numberOfProperties': 125
}, {
'priceRangeStart': '5100000',
'numberOfProperties': 170
}, {
'priceRangeStart': '5200000',
'numberOfProperties': 290
}, {
'priceRangeStart': '5300000',
'numberOfProperties': 660
}, {
'priceRangeStart': '5400000',
'numberOfProperties': 450
}, {
'priceRangeStart': '5500000',
'numberOfProperties': 359
}, {
'priceRangeStart': '5600000',
'numberOfProperties': 740
}, {
'priceRangeStart': '5700000',
'numberOfProperties': 894
}, {
'priceRangeStart': '5900000',
'numberOfProperties': 547
}, {
'priceRangeStart': '6000000',
'numberOfProperties': 1250
}];

var property_price = 5050000;

// variables and helpers
var margin = {
top: 0,
right: 20,
bottom: 25,
left: 0
},
width = 370,
height = 200;

var formatComma = d3.format(',');


// responsive SVG
// create responsive svg container for the graph
var svg = d3.select("body")
.append('svg')
.attr('preserveAspectRatio', 'none')
.attr('viewBox', '0 0 370 225')
//class to make it responsive
.classed('svg-content-responsive', true);

// creating x and y scales
var x = d3.scaleBand().rangeRound([0, width]).paddingOuter(0.5).paddingInner(0.6),
x1 = d3.scaleBand().rangeRound([0, width]),
y = d3.scaleLinear().rangeRound([height, 0]),
y1 = d3.scaleLinear().rangeRound([0, (height - 100)]); //

// creating the group object
var g = svg.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

// processing the data
var new_dataset = data;
var transformation = [];

transformation = new_dataset.map(el => ({
priceRangeStart: el.priceRangeStart,
numberOfProperties: el.numberOfProperties
}));

transformation.forEach(function(d) {
d.priceRangeStart = +d.priceRangeStart;
d.numberOfProperties = +d.numberOfProperties;
return d;
});

// using lodash
var minValue = _.first(transformation).priceRangeStart;
var maxValue = _.last(transformation).priceRangeStart;

// get max number of properties value
var maxNrProperties = d3.max(transformation, function(d) {
return d.numberOfProperties;
});

// x and y value domains
x.domain(transformation.map(function(d) {
return d.priceRangeStart;
}));
x1.domain(transformation.map(function(d) {
return d.priceRangeStart;
}));
y.domain([0, ((d3.max(transformation, function(d) {
return d.numberOfProperties;
})) + (1.15 * maxNrProperties))]);
y1.domain([0, (d3.max(transformation, function(d) {
return d.numberOfProperties;
}))]);

// create x axis (for guiding purposes) and then hide it
g.append('g')
.attr('transform', 'translate(0,' + height + ')')
.attr('class', 'axis axis--x')
.call(d3.axisBottom(x))
.style('opacity', 0)
.selectAll('text').remove();

// text for min price value and translate it to the start position of the first bar
g.append('text')
.attr('transform', 'translate(' + (x(_.first(transformation).priceRangeStart)) + ' ,' + (height * 1.1) + ')')
.style('text-anchor', 'start')
.style('font-size', '12px')
.text('CHF ' + formatComma(minValue));

// text for max price value and translate it to the end position of the last bar
g.append('text')
.attr('transform', 'translate(' + (x(_.last(transformation).priceRangeStart) + x.bandwidth()) + ' ,' + (height * 1.1) + ')')
.style('text-anchor', 'end')
.style('font-size', '12px')
.text('CHF ' + formatComma(maxValue));

// apppend the grey bars to the graph and styling them
g.selectAll('.bar')
.data(transformation)
.enter().append('rect')
.attr('class', 'bar')
.attr('x', function(d) {
return x(d.priceRangeStart);
})
.attr('y', function(d) {
return height - y1(maxNrProperties);
})
.attr('width', x.bandwidth())
.attr('height', function(d) {
return y1(maxNrProperties);
})
.style('fill', '#A4A9AD')
.style('opacity', 0.2);

// apppend the orange bars to the graph and styling them
g.selectAll(null)
.data(transformation)
.enter().append('rect')
.attr('class', 'bar')
.attr('x', function(d) {
return x(d.priceRangeStart);
})
.attr('y', function(d) {
return y(d.numberOfProperties);
})
.attr('width', x.bandwidth())
.attr('height', function(d) {
return height - y(d.numberOfProperties);
})
.style('fill', '#EDAA00')
.style('opacity', 1);

var lineIndex = d3.bisectLeft(x.domain(), property_price);

var line = svg.append("line")
.attr("x1", x(x.domain()[lineIndex]) - x.step() / 2 + x.bandwidth() / 2)
.attr("x2", x(x.domain()[lineIndex]) - x.step() / 2 + x.bandwidth() / 2)
.attr("y1", height - 100)
.attr("y2", height)
.style("stroke", "gray")
.style("stroke-width", 2)
.style("stroke-dasharray", "2,2")
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

关于javascript - 将垂直线添加到 d3js 条形图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46827224/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com