D3.js JavaScript 模板中的图表(jsRender/jsViews、jquery tmpl 等)
D3.js Graphs in JavaScript Templates (jsRender/jsViews, jquery tmpl, etc.)
我一直在尝试创建一个页面,该页面使用 JavaScript 模板,其中包含使用 d3.js 制作的图表,以显示有关每个库存项目的信息(在本例中,我有一个数组 JSON 包含晶体管数据的 blob。)例如,我需要样板 "Absolute Max Ratings" table 后跟图形,例如一系列栅极电压的阻抗曲线。这是我目前所拥有的:
var partData = [
{
name: "IRF10",
maxRatings:
{
vds: 200,
vgs: 20,
id: 2.1,
pd: 36
},
impedanceGraph:
[
[1, 0.7],
[2, 1.6],
[3, 2.0],
[4, 2.5]
]
},
{
name: "2n7000",
maxRatings:
{
vds: 60,
vgs: 20,
id: 0.2,
pd: 0.4
},
impedanceGraph:
[
[1, 0.6],
[2, 1.5],
[3, 1.9],
[4, 2.4]
]
}
]
$('#container').html($('#partTemplate').render(partData));
<script id="partTemplate" type="text/x-jsrender">
<div style="background-color:mintcream">
<h2>{{>name}}</h2>
Max Ratings
{{props maxRatings}}
<li>{{>key}}: {{>prop}}</li>
{{/props}}
<br />
Impedance Graph: <br />
PLACE_D3_GRAPH_HERE
</div>
</script>
<div id="container"></div>
这是我的 jsfiddle,因为 jsRender 不能正常工作:
http://jsfiddle.net/xaty70b6/
由于 D3.js 似乎通过将 SVG 元素附加到正文并将数据插入 selection 来工作,所以我被引导相信我需要以某种方式 select 使用 jquery 的模板实例并将其提供给 D3.js 以构建图形,但我不知道如何在构建行时获取模板实例。真的,我想要做的就是使用 JSON blob 中为该实例提供的数据,在我的模板实例中显示一个 D3.js 图表。是否有另一种方法可以使用相关数据数组插入要传递到 D3.js 的 SVG?
我没有使用过 D3.js,但在研究它时,很明显 D3 直接在 DOM 上工作 - 而 JsRender 渲染独立于 DOM -并生成一个 HTML 字符串,然后您自己将其插入 DOM。
然而 JsViews 完全是 'DOM aware' 并且在模板实例、数据和 DOM 之间进行绑定。所以我建议使用 JsViews。
此外,这开启了使用 JsViews 数据绑定以交互方式更新数据的可能性。 JsView 的数据绑定当然与 D3 的数据绑定不同,但是探索将它们集成在一起是很有趣的。
所以这里(在下面的代码片段中,还有这里:http://jsfiddle.net/BorisMoore/Lbfn5aog/1/)是一种方法。
我创建了一个自定义的 {{barChart}} 标签,用于集成 D3 图表:
$.views.tags("barChart", {
init: function(tagCtx, linkCtx) {
this.data = tagCtx.args[0];
this.svg = initChart(linkCtx.elem, this.data);
},
onAfterLink: function(tagCtx, linkCtx) {
var tag = this;
$.observable(tag.data).observeAll(function() {
updateChart(tag.data, tag.svg);
});
}
});
并将其包含在模板中,如下所示:
<div class="chart" data-link="{barChart impedanceGraph}"></div>
(也可以用标签呈现的 div 创建一个版本,这样你就可以写成 {^{barChart impedanceGraph /}}
...)
如果您不需要动态数据绑定,您可以省略 onAfterLink
方法。
但是如果你包含它,那么现在你可以修改文本框中的值,数据将由 JsViews 更新。数据链接的 barChart 标记将获取更改并将其传递给 D3,D3 将重新计算列,并根据需要使用新的比例因子。
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 180 - margin.left - margin.right,
height = 200 - margin.top - margin.bottom;
function scaleChart(data) {
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(10, "%");
x.domain(data.map(function(d) {
return d.name; }));
y.domain([0, d3.max(data, function(d) {
return d.amt;
})]);
return {x:x, y:y, xAxis: xAxis, yAxis: yAxis};
}
function initChart(element, data) {
var chart = scaleChart(data);
var svg = d3.select(element).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 + ")");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(chart.xAxis);
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) {
return chart.x(d.name);
})
.attr("width", chart.x.rangeBand())
.attr("y", function(d) { return chart.y(d.amt); })
.attr("height", function(d) {
return height - chart.y(d.amt);
});
return svg;
}
function updateChart(data, svg) {
var chart = scaleChart(data);
svg.selectAll(".bar")
.data(data)
.attr("y", function(d) { return chart.y(d.amt); })
.attr("height", function(d) {
return height - chart.y(d.amt);
});
}
var partData = [
{
name: "IRF10",
maxRatings:
{
vds: 200,
vgs: 20,
id: 2.1,
pd: 36
},
impedanceGraph:
[
{name: 1, amt: 0.7},
{name: 2, amt: 1.6},
{name: 3, amt: 2.0},
{name: 4, amt: 2.0},
{name: 5, amt: 0.5}
]
},
{
name: "2n7000",
maxRatings:
{
vds: 60,
vgs: 20,
id: 0.2,
pd: 0.4
},
impedanceGraph:
[
{name: 1, amt: 0.6},
{name: 2, amt: 1.5},
{name: 3, amt: 1.9},
{name: 4, amt: 2.4}
]
}
]
$.views.tags("barChart", {
init: function(tagCtx, linkCtx) {
this.data = tagCtx.args[0];
this.svg = initChart(linkCtx.elem, this.data);
},
onAfterLink: function(tagCtx, linkCtx) {
var tag = this;
$.observable(tag.data).observeAll(function() {
updateChart(tag.data, tag.svg);
});
}
});
var tmpl = $.templates("#partTemplate");
tmpl.link('#container', partData);
li {
list-style:none
}
.bar {
fill: steelblue;
}
.bar:hover {
fill: brown;
}
.axis {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.x.axis path {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//www.jsviews.com/download/jsviews.js"></script>
<script id="partTemplate" type="text/x-jsrender">
<div style="background-color:mintcream">
<h2>{{>name}}</h2>
Max Ratings
<ul>
{{props maxRatings}}
<li>{{>key}}: {{>prop}}</li>
{{/props}}
</ul>
<br />
Impedance Graph: <br />
<ul>
{{for impedanceGraph}}
<li><input data-link="amt" /></li>
{{/for}}
</ul>
<div class="chart" data-link="{barChart impedanceGraph}"></div>
</div>
</script>
<div id="container"></div>
我一直在尝试创建一个页面,该页面使用 JavaScript 模板,其中包含使用 d3.js 制作的图表,以显示有关每个库存项目的信息(在本例中,我有一个数组 JSON 包含晶体管数据的 blob。)例如,我需要样板 "Absolute Max Ratings" table 后跟图形,例如一系列栅极电压的阻抗曲线。这是我目前所拥有的:
var partData = [
{
name: "IRF10",
maxRatings:
{
vds: 200,
vgs: 20,
id: 2.1,
pd: 36
},
impedanceGraph:
[
[1, 0.7],
[2, 1.6],
[3, 2.0],
[4, 2.5]
]
},
{
name: "2n7000",
maxRatings:
{
vds: 60,
vgs: 20,
id: 0.2,
pd: 0.4
},
impedanceGraph:
[
[1, 0.6],
[2, 1.5],
[3, 1.9],
[4, 2.4]
]
}
]
$('#container').html($('#partTemplate').render(partData));
<script id="partTemplate" type="text/x-jsrender">
<div style="background-color:mintcream">
<h2>{{>name}}</h2>
Max Ratings
{{props maxRatings}}
<li>{{>key}}: {{>prop}}</li>
{{/props}}
<br />
Impedance Graph: <br />
PLACE_D3_GRAPH_HERE
</div>
</script>
<div id="container"></div>
这是我的 jsfiddle,因为 jsRender 不能正常工作: http://jsfiddle.net/xaty70b6/
由于 D3.js 似乎通过将 SVG 元素附加到正文并将数据插入 selection 来工作,所以我被引导相信我需要以某种方式 select 使用 jquery 的模板实例并将其提供给 D3.js 以构建图形,但我不知道如何在构建行时获取模板实例。真的,我想要做的就是使用 JSON blob 中为该实例提供的数据,在我的模板实例中显示一个 D3.js 图表。是否有另一种方法可以使用相关数据数组插入要传递到 D3.js 的 SVG?
我没有使用过 D3.js,但在研究它时,很明显 D3 直接在 DOM 上工作 - 而 JsRender 渲染独立于 DOM -并生成一个 HTML 字符串,然后您自己将其插入 DOM。
然而 JsViews 完全是 'DOM aware' 并且在模板实例、数据和 DOM 之间进行绑定。所以我建议使用 JsViews。
此外,这开启了使用 JsViews 数据绑定以交互方式更新数据的可能性。 JsView 的数据绑定当然与 D3 的数据绑定不同,但是探索将它们集成在一起是很有趣的。
所以这里(在下面的代码片段中,还有这里:http://jsfiddle.net/BorisMoore/Lbfn5aog/1/)是一种方法。
我创建了一个自定义的 {{barChart}} 标签,用于集成 D3 图表:
$.views.tags("barChart", {
init: function(tagCtx, linkCtx) {
this.data = tagCtx.args[0];
this.svg = initChart(linkCtx.elem, this.data);
},
onAfterLink: function(tagCtx, linkCtx) {
var tag = this;
$.observable(tag.data).observeAll(function() {
updateChart(tag.data, tag.svg);
});
}
});
并将其包含在模板中,如下所示:
<div class="chart" data-link="{barChart impedanceGraph}"></div>
(也可以用标签呈现的 div 创建一个版本,这样你就可以写成 {^{barChart impedanceGraph /}}
...)
如果您不需要动态数据绑定,您可以省略 onAfterLink
方法。
但是如果你包含它,那么现在你可以修改文本框中的值,数据将由 JsViews 更新。数据链接的 barChart 标记将获取更改并将其传递给 D3,D3 将重新计算列,并根据需要使用新的比例因子。
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 180 - margin.left - margin.right,
height = 200 - margin.top - margin.bottom;
function scaleChart(data) {
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(10, "%");
x.domain(data.map(function(d) {
return d.name; }));
y.domain([0, d3.max(data, function(d) {
return d.amt;
})]);
return {x:x, y:y, xAxis: xAxis, yAxis: yAxis};
}
function initChart(element, data) {
var chart = scaleChart(data);
var svg = d3.select(element).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 + ")");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(chart.xAxis);
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) {
return chart.x(d.name);
})
.attr("width", chart.x.rangeBand())
.attr("y", function(d) { return chart.y(d.amt); })
.attr("height", function(d) {
return height - chart.y(d.amt);
});
return svg;
}
function updateChart(data, svg) {
var chart = scaleChart(data);
svg.selectAll(".bar")
.data(data)
.attr("y", function(d) { return chart.y(d.amt); })
.attr("height", function(d) {
return height - chart.y(d.amt);
});
}
var partData = [
{
name: "IRF10",
maxRatings:
{
vds: 200,
vgs: 20,
id: 2.1,
pd: 36
},
impedanceGraph:
[
{name: 1, amt: 0.7},
{name: 2, amt: 1.6},
{name: 3, amt: 2.0},
{name: 4, amt: 2.0},
{name: 5, amt: 0.5}
]
},
{
name: "2n7000",
maxRatings:
{
vds: 60,
vgs: 20,
id: 0.2,
pd: 0.4
},
impedanceGraph:
[
{name: 1, amt: 0.6},
{name: 2, amt: 1.5},
{name: 3, amt: 1.9},
{name: 4, amt: 2.4}
]
}
]
$.views.tags("barChart", {
init: function(tagCtx, linkCtx) {
this.data = tagCtx.args[0];
this.svg = initChart(linkCtx.elem, this.data);
},
onAfterLink: function(tagCtx, linkCtx) {
var tag = this;
$.observable(tag.data).observeAll(function() {
updateChart(tag.data, tag.svg);
});
}
});
var tmpl = $.templates("#partTemplate");
tmpl.link('#container', partData);
li {
list-style:none
}
.bar {
fill: steelblue;
}
.bar:hover {
fill: brown;
}
.axis {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.x.axis path {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//www.jsviews.com/download/jsviews.js"></script>
<script id="partTemplate" type="text/x-jsrender">
<div style="background-color:mintcream">
<h2>{{>name}}</h2>
Max Ratings
<ul>
{{props maxRatings}}
<li>{{>key}}: {{>prop}}</li>
{{/props}}
</ul>
<br />
Impedance Graph: <br />
<ul>
{{for impedanceGraph}}
<li><input data-link="amt" /></li>
{{/for}}
</ul>
<div class="chart" data-link="{barChart impedanceGraph}"></div>
</div>
</script>
<div id="container"></div>