我试图了解使用 d3.selectAll.data.enter() 循环遍历数据集并绘制它的好处。
var data = [4, 8, 15, 16, 23, 42];
var x = d3.scale.linear()
.domain([0, d3.max(data)])
.range([0, 420]);
let chartsvg = d3.select(".chart").append("svg");
chartsvg.selectAll("rect")
.data(data)
.enter()
.append("rect")
.attr("x", 0)
.attr("y", function(d, i) {
return 25*i;
})
.attr("width", function(d) {
return x(d);
})
.attr("height", 20)
.attr("fill", "#f3b562");
var data = [4, 8, 15, 16, 23, 42];
var x = d3.scale.linear()
.domain([0, d3.max(data)])
.range([0, 420]);
let chartsvg = d3.select(".chart").append("svg");
data.map(function(d, i){
chartsvg.append("rect")
.attr("x", 0)
.attr("y", 25*i)
.attr("width", x(d))
.attr("height", 20)
.attr("fill", "#f3b562");
});
最佳答案
D3 代表数据驱动文档
D3 中最强大的功能(也就是库的名称)是将数据绑定(bind)到 DOM 元素的能力。通过这样做,您可以通过多种方式根据绑定(bind)数据操作这些 DOM 元素,例如(但不限于):
map()在您的问题中使用方法(与 forEach() 相同),您可能会在开始时节省几行,但最终会得到一个笨拙的代码来处理。让我们来看看它:map() 创建条形图方法:var h = 250,
w = 500,
p = 40;
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
var data = [{
group: "foo",
value: 14,
name: "A"
}, {
group: "foo",
value: 35,
name: "B"
}, {
group: "foo",
value: 87,
name: "C"
}, {
group: "foo",
value: 12,
name: "D"
}, {
group: "bar",
value: 84,
name: "E"
}, {
group: "bar",
value: 65,
name: "F"
}, {
group: "bar",
value: 34,
name: "G"
}, {
group: "baz",
value: 98,
name: "H"
}, {
group: "baz",
value: 12,
name: "I"
}, {
group: "baz",
value: 43,
name: "J"
}, {
group: "baz",
value: 66,
name: "K"
}, {
group: "baz",
value: 42,
name: "L"
}];
var color = d3.scaleOrdinal(d3.schemeCategory10);
var xScale = d3.scaleLinear()
.range([0, w - p])
.domain([0, d3.max(data, function(d) {
return d.value
})]);
var yScale = d3.scaleBand()
.range([0, h])
.domain(data.map(function(d) {
return d.name
}))
.padding(0.1);
data.map(function(d, i) {
svg.append("rect")
.attr("x", p)
.attr("y", yScale(d.name))
.attr("width", xScale(d.value))
.attr("height", yScale.bandwidth())
.attr("fill", color(d.group));
});
var axis = d3.axisLeft(yScale);
var gY = svg.append("g").attr("transform", "translate(" + p + ",0)")
.call(axis); <script src="https://d3js.org/d3.v4.min.js"></script>var h = 250,
w = 500,
p = 40;
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
var data = [{
group: "foo",
value: 14,
name: "A"
}, {
group: "foo",
value: 35,
name: "B"
}, {
group: "foo",
value: 87,
name: "C"
}, {
group: "foo",
value: 12,
name: "D"
}, {
group: "bar",
value: 84,
name: "E"
}, {
group: "bar",
value: 65,
name: "F"
}, {
group: "bar",
value: 34,
name: "G"
}, {
group: "baz",
value: 98,
name: "H"
}, {
group: "baz",
value: 12,
name: "I"
}, {
group: "baz",
value: 43,
name: "J"
}, {
group: "baz",
value: 66,
name: "K"
}, {
group: "baz",
value: 42,
name: "L"
}];
var color = d3.scaleOrdinal(d3.schemeCategory10);
var xScale = d3.scaleLinear()
.range([0, w - p])
.domain([0, d3.max(data, function(d) {
return d.value
})]);
var yScale = d3.scaleBand()
.range([0, h])
.domain(data.map(function(d) {
return d.name
}))
.padding(0.1);
svg.selectAll(null)
.data(data, function(d) {
return d.name
})
.enter()
.append("rect")
.attr("x", p)
.attr("y", function(d) {
return yScale(d.name)
})
.attr("width", function(d) {
return xScale(d.value)
})
.attr("height", yScale.bandwidth())
.attr("fill", function(d) {
return color(d.group)
});
var axis = d3.axisLeft(yScale);
var gY = svg.append("g").attr("transform", "translate(" + p + ",0)")
.call(axis); <script src="https://d3js.org/d3.v4.min.js"></script>map()长一点方法,2行更长。> Selection
> _groups: Array(1)
> 0: Array(1)
> 0: rect
> __data__: Object
group: "bar"
name: "G"
value: 34
由于此代码实际上将数据绑定(bind)到 DOM 元素,因此您可以使用 map() 以一种很麻烦(至少可以说)的方式操作它们。方法。我将在下一个片段中展示这一点,该片段将用于提出挑战。data 中的每个组一个数组(所有组的第四个)。当您单击该按钮时,它会过滤数据并相应地更新图表:var h = 250,
w = 500,
p = 40;
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
var g1 = svg.append("g")
var g2 = svg.append("g")
var data = [{
group: "foo",
value: 14,
name: "A"
}, {
group: "foo",
value: 35,
name: "B"
}, {
group: "foo",
value: 87,
name: "C"
}, {
group: "foo",
value: 12,
name: "D"
}, {
group: "bar",
value: 84,
name: "E"
}, {
group: "bar",
value: 65,
name: "F"
}, {
group: "bar",
value: 34,
name: "G"
}, {
group: "baz",
value: 98,
name: "H"
}, {
group: "baz",
value: 12,
name: "I"
}, {
group: "baz",
value: 43,
name: "J"
}, {
group: "baz",
value: 66,
name: "K"
}, {
group: "baz",
value: 42,
name: "L"
}];
var color = d3.scaleOrdinal(d3.schemeCategory10);
var xScale = d3.scaleLinear()
.range([0, w - p])
.domain([0, d3.max(data, function(d) {
return d.value
})]);
var yScale = d3.scaleBand()
.range([0, h])
.domain(data.map(function(d) {
return d.name
}))
.padding(0.1);
var axis = d3.axisLeft(yScale);
var gY = g2.append("g").attr("transform", "translate(" + p + ",0)")
.call(axis);
draw(data);
function draw(data) {
yScale.domain(data.map(function(d) {
return d.name
}))
var rects = g1.selectAll("rect")
.data(data, function(d) {
return d.name
})
rects.enter()
.append("rect")
.attr("x", p)
.attr("y", function(d) {
return yScale(d.name)
})
.attr("width", 0)
.attr("height", yScale.bandwidth())
.attr("fill", function(d) {
return color(d.group)
})
.transition()
.duration(1000)
.attr("width", function(d) {
return xScale(d.value)
});
rects.transition()
.duration(1000)
.attr("x", p)
.attr("y", function(d) {
return yScale(d.name)
})
.attr("width", function(d) {
return xScale(d.value)
})
.attr("height", yScale.bandwidth())
.attr("fill", function(d) {
return color(d.group)
});
rects.exit()
.transition()
.duration(1000)
.attr("width", 0)
.remove();
gY.transition().duration(1000).call(axis);
};
d3.selectAll("button").on("click", function() {
var thisValue = this.id;
var newData = thisValue === "all" ? data : data.filter(function(d) {
return d.group === thisValue;
});
draw(newData)
}); <script src="https://d3js.org/d3.v4.min.js"></script>
<button id="foo">Foo</button>
<button id="bar">Bar</button>
<button id="baz">Baz</button>
<button id="all">All</button>
<br>
<br>map()方法,即不绑定(bind)任何数据。做我在这里做的所有转换。您将尝试重新创建的代码是 on("click") 中的所有代码。功能。name属性(property):.data(data, function(d) {
return d.name
})
这是代码,请等待1秒后再点击“更新”:var h = 250,
w = 500,
p = 40;
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
var data2 = [{
group: "foo",
value: 10,
name: "A"
}, {
group: "foo",
value: 20,
name: "B"
}, {
group: "foo",
value: 30,
name: "C"
}, {
group: "foo",
value: 40,
name: "D"
}, {
group: "bar",
value: 50,
name: "E"
}, {
group: "bar",
value: 60,
name: "F"
}, {
group: "bar",
value: 70,
name: "G"
}, {
group: "baz",
value: 80,
name: "H"
}, {
group: "baz",
value: 85,
name: "I"
}, {
group: "baz",
value: 90,
name: "J"
}, {
group: "baz",
value: 95,
name: "K"
}, {
group: "baz",
value: 100,
name: "L"
}];
var data = [{
group: "foo",
value: 14,
name: "A"
}, {
group: "foo",
value: 35,
name: "B"
}, {
group: "foo",
value: 87,
name: "C"
}, {
group: "foo",
value: 12,
name: "D"
}, {
group: "bar",
value: 84,
name: "E"
}, {
group: "bar",
value: 65,
name: "F"
}, {
group: "bar",
value: 34,
name: "G"
}, {
group: "baz",
value: 98,
name: "H"
}, {
group: "baz",
value: 12,
name: "I"
}, {
group: "baz",
value: 43,
name: "J"
}, {
group: "baz",
value: 66,
name: "K"
}, {
group: "baz",
value: 42,
name: "L"
}];
var color = d3.scaleOrdinal(d3.schemeCategory10);
var xScale = d3.scaleLinear()
.range([0, w - p])
.domain([0, d3.max(data, function(d) {
return d.value
})]);
var yScale = d3.scaleBand()
.range([0, h])
.domain(data.map(function(d) {
return d.name
}))
.padding(0.1);
svg.selectAll(".bars")
.data(data, function(d) {
return d.name
})
.enter()
.append("rect")
.attr("class", "bars")
.attr("x", p)
.attr("y", function(d) {
return yScale(d.name)
})
.attr("width", function(d) {
return xScale(d.value)
})
.attr("height", yScale.bandwidth())
.attr("fill", function(d) {
return color(d.group)
})
var axis = d3.axisLeft(yScale);
var gY = svg.append("g").attr("transform", "translate(" + p + ",0)")
.call(axis);
setTimeout(function() {
data.sort(function(a, b) {
return d3.ascending(a.value, b.value)
});
yScale.domain(data.map(function(d) {
return d.name
}));
svg.selectAll(".bars").data(data, function(d) {
return d.name
})
.transition()
.duration(500)
.attr("y", function(d) {
return yScale(d.name)
})
.attr("width", function(d) {
return xScale(d.value)
});
gY.transition().duration(1000).call(axis);
}, 1000)
d3.selectAll("button").on("click", function() {
svg.selectAll(".bars").data(data2, function(d) {
return d.name
})
.transition()
.duration(500)
.attr("y", function(d) {
return yScale(d.name)
})
.attr("width", function(d) {
return xScale(d.value)
});
gY.transition().duration(1000).call(axis);
}) <script src="https://d3js.org/d3.v4.min.js"></script>
<button>Update</button>
<br>
<br>.on("click") 中的代码,仅此而已...svg.selectAll(".bars").data(data2, function(d) {
return d.name
})
.transition()
.duration(500)
.attr("y", function(d) {
return yScale(d.name)
})
.attr("width", function(d) {
return xScale(d.value)
});
gY.transition().duration(1000).call(axis);
... 到执行 的代码一样的 ,但对于您的map()方法。map()当您第一次绘制元素时,方法可能会为您节省 2 行。但是,这会使以后的事情变得非常麻烦。
关于javascript - Array.map() 与 d3.selectAll().data.enter(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44354851/
我怎样才能完成http://php.net/manual/en/function.call-user-func-array.php在ruby中?所以我可以这样做:classAppdeffoo(a,b)putsa+benddefbarargs=[1,2]App.send(:foo,args)#doesn'tworkApp.send(:foo,args[0],args[1])#doeswork,butdoesnotscaleendend 最佳答案 尝试分解数组App.send(:foo,*args)
通过rubykoans.com,我在about_array_assignment.rb中遇到了这两段代码你怎么知道第一个是非并行赋值,第二个是一个变量的并行赋值?在我看来,除了命名差异之外,代码几乎完全相同。4deftest_non_parallel_assignment5names=["John","Smith"]6assert_equal["John","Smith"],names7end45deftest_parallel_assignment_with_one_variable46first_name,=["John","Smith"]47assert_equal'John
“输出”是一个序列化的OpenStruct。定义标题try(:output).try(:data).try(:title)结束什么会更好?:) 最佳答案 或者只是这样:deftitleoutput.data.titlerescuenilend 关于ruby-on-rails-更好的替代方法try(:output).try(:data).try(:name)?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.c
这个问题在这里已经有了答案:Arraysmisbehaving(1个回答)关闭6年前。是否应该这样,即我误解了,还是错误?a=Array.new(3,Array.new(3))a[1].fill('g')=>[["g","g","g"],["g","g","g"],["g","g","g"]]它不应该导致:=>[[nil,nil,nil],["g","g","g"],[nil,nil,nil]]
我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的
我正在使用Rails3.2.3和Ruby1.9.3p0。我发现我经常需要确定某个字符串是否出现在选项列表中。看来我可以使用Ruby数组.includemethod:或正则表达式equals-tildematchshorthand用竖线分隔选项:就性能而言,一个比另一个好吗?还有更好的方法吗? 最佳答案 总结:Array#include?包含String元素,在接受和拒绝输入时均胜出,对于您的示例只有三个可接受的值。对于要检查的更大的集合,看起来Set#include?和String元素可能会获胜。如何测试我们应该根据经验对此进行测试
我需要从json记录中获取一些值并像下面这样提取curr_json_doc['title']['genre'].map{|s|s['name']}.join(',')但对于某些记录,curr_json_doc['title']['genre']可以为空。所以我想对map和join()使用try函数。我试过如下curr_json_doc['title']['genre'].try(:map,{|s|s['name']}).try(:join,(','))但是没用。 最佳答案 你没有正确传递block。block被传递给参数括号外的方法
如thisanswer中所述,Array.new(size,object)创建一个数组,其中size引用相同的object。hash=Hash.newa=Array.new(2,hash)a[0]['cat']='feline'a#=>[{"cat"=>"feline"},{"cat"=>"feline"}]a[1]['cat']='Felix'a#=>[{"cat"=>"Felix"},{"cat"=>"Felix"}]为什么Ruby会这样做,而不是对object进行dup或clone? 最佳答案 因为那是thedocumenta
Enumerable#each和Enumerable#map的区别在于返回的是接收者还是映射后的结果。回到接收者是微不足道的,你通常不需要在each之后继续一个方法链,比如each{...}.another_method(我可能没见过这样的案例。即使你想回到接收者那里,你也可以通过tap来实现)。所以我认为所有或者大部分使用Enumerable#each的情况都可以用Enumerable#map代替。我错了吗?如果我是对的,each的目的是什么?map是否比each慢?编辑:我知道当您对返回值不感兴趣时使用each是一种常见的做法。我对这种做法是否存在不感兴趣,但感兴趣的是,除了从
我有这个:AccountSummary我想单击该链接,但在使用link_to时出现错误。我试过:bot.click(page.link_with(:href=>/menu_home/))bot.click(page.link_with(:class=>'top_level_active'))bot.click(page.link_with(:href=>/AccountSummary/))我得到的错误是:NoMethodError:nil:NilClass的未定义方法“[]” 最佳答案 那是一个javascript链接。Mechan