我为D3.js写了一个名为d3-marcon
的插件,它实现了Mike Bostock's margin conventions。例如,而不是必须写:
var margin = {top: 10, bottom: 10, left: 10, right: 10},
width = window.innerWidth - margin.left - margin.right,
height = window.innerHeight - margin.top - margin.bottom,
svg = d3.select("body").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 + ")");
你可以写:
var setup = d3.marcon({top: 10, bottom: 10, left: 10, right: 10, width: window.innerWidth, height: window.innerHeight}),
margin = setup.margin,
width = setup.width,
height = setup.height,
svg = setup.svg;
如您所见,它通过将选项对象传递给marcon()
函数来工作。如果您未指定任何选项,则默认为0
表示所有页边距,900
表示宽度,600
表示高度,并将svg元素附加到"body"
。因此,您只需使用一行代码var setup = d3.marcon()
即可快速启动并运行,然后在您想要更改时即可传递选项。
这很有用,但它仍然不像真正的D3功能。真正的D3函数允许将函数链接在一起,而不是传递选项对象。因此,D3代码不是d3.marcon({element: ".viz"})
,而是d3.marcon().element(".viz")
。
D3代码还允许您将其他功能传递给链接函数(例如d3.method().chainedFunction(function(d) { return d.value; })
),以便您可以根据数据更新对象的属性。
显然,我的插件没有做这些事情。我花了几个小时看现有的D3模块,试图找出它们是如何工作的,但我没有到达任何地方。任何人都可以建议如何使我的代码像适当的D3模块一样工作?或者,如果没有,那么阅读一个很好的教程?
我链接到上面的存储库,但是here it is again。并here is a block展示了它是如何运作的。
答案 0 :(得分:3)
这是我的建议,基于Nick Zhu在他的书“数据可视化与D3 4.x ”中的方法。
基本上,我们用对象创建一个函数......
function marcon() {
var instance = {};
}
...并分别设置每个方法:
instance.top = function(d) {
if (!arguments.length) return top;
top = d;
return instance;
};
最后,您使用render()
调用渲染部分:
marcon().top(10)
.left(10)
//etc...
.render();
这种方法的好处在于,正如您所要求的那样,它允许链接。例如,您可以像这样创建SVG:
var mySvg = marcon();
mySvg.top(20)
.left(10)
.right(10)
.bottom(10)
.height(200)
.width(200)
.element("body")
.render();
这是一个演示:
function marcon() {
var instance = {};
var top = 10,
bottom = 0,
left = 0,
right = 0,
width = 900,
height = 600,
element = "body",
innerWidth, innerHeight, svg;
instance.top = function(d) {
if (!arguments.length) return top;
top = d;
return instance;
};
instance.left = function(d) {
if (!arguments.length) return left;
left = d;
return instance;
};
instance.right = function(d) {
if (!arguments.length) return right;
right = d;
return instance;
};
instance.bottom = function(d) {
if (!arguments.length) return bottom;
bottom = d;
return instance;
};
instance.width = function(d) {
if (!arguments.length) return width;
width = d;
return instance;
};
instance.height = function(d) {
if (!arguments.length) return height;
height = d;
return instance;
};
instance.element = function(d) {
if (!arguments.length) return element;
element = d;
return instance;
};
instance.innerWidth = function() {
return innerWidth;
};
instance.innerHeight = function() {
return innerHeight;
};
instance.svg = function() {
return svg;
};
instance.render = function() {
innerWidth = width - left - right;
innerHeight = height - top - bottom;
svg = d3.select(element)
.append("svg")
.attr("width", innerWidth + left + right)
.attr("height", innerHeight + top + bottom)
.append("g")
.attr("transform", "translate(" + left + ", " + top + ")");
}
return instance;
}
var mySvg = marcon();
mySvg.top(20)
.left(10)
.right(10)
.bottom(20)
.height(200)
.width(200)
.element(".testDiv")
.render();
var rect = mySvg.svg()
.append("rect")
.attr("width", mySvg.innerWidth())
.attr("height", mySvg.innerHeight())
.style("fill", "teal")

svg {
background-color: tan;
}

<script src="https://d3js.org/d3.v4.min.js"></script>
<div class="testDiv"></div>
&#13;
此外,它允许默认值。如果您未设置setter,则默认为指定值。在这里,如果我们不设置宽度,则默认为900:
function marcon() {
var instance = {};
var top = 10,
bottom = 0,
left = 0,
right = 0,
width = 900,
height = 600,
element = "body",
innerWidth, innerHeight, svg;
instance.top = function(d) {
if (!arguments.length) return top;
top = d;
return instance;
};
instance.left = function(d) {
if (!arguments.length) return left;
left = d;
return instance;
};
instance.right = function(d) {
if (!arguments.length) return right;
right = d;
return instance;
};
instance.bottom = function(d) {
if (!arguments.length) return bottom;
bottom = d;
return instance;
};
instance.width = function(d) {
if (!arguments.length) return width;
width = d;
return instance;
};
instance.height = function(d) {
if (!arguments.length) return height;
height = d;
return instance;
};
instance.element = function(d) {
if (!arguments.length) return element;
element = d;
return instance;
};
instance.innerWidth = function() {
return innerWidth;
};
instance.innerHeight = function() {
return innerHeight;
};
instance.svg = function() {
return svg;
};
instance.render = function() {
innerWidth = width - left - right;
innerHeight = height - top - bottom;
svg = d3.select(element)
.append("svg")
.attr("width", innerWidth + left + right)
.attr("height", innerHeight + top + bottom)
.append("g")
.attr("transform", "translate(" + left + ", " + top + ")");
}
return instance;
}
var mySvg = marcon();
mySvg.top(20)
.left(10)
.right(10)
.bottom(20)
.height(200)
.element("body")
.render();
var rect = mySvg.svg()
.append("rect")
.attr("width", mySvg.innerWidth())
.attr("height", mySvg.innerHeight())
.style("fill", "teal")
&#13;
svg {
background-color: tan;
}
&#13;
<script src="https://d3js.org/d3.v4.min.js"></script>
<div class="testDiv"></div>
&#13;
最后,您可以使用getters,例如:
marcon().top();
它为您提供了价值。这是一个演示,看一下控制台:
function marcon() {
var instance = {};
var top = 10,
bottom = 0,
left = 0,
right = 0,
width = 900,
height = 600,
element = "body",
innerWidth, innerHeight, svg;
instance.top = function(d) {
if (!arguments.length) return top;
top = d;
return instance;
};
instance.left = function(d) {
if (!arguments.length) return left;
left = d;
return instance;
};
instance.right = function(d) {
if (!arguments.length) return right;
right = d;
return instance;
};
instance.bottom = function(d) {
if (!arguments.length) return bottom;
bottom = d;
return instance;
};
instance.width = function(d) {
if (!arguments.length) return width;
width = d;
return instance;
};
instance.height = function(d) {
if (!arguments.length) return height;
height = d;
return instance;
};
instance.element = function(d) {
if (!arguments.length) return element;
element = d;
return instance;
};
instance.innerWidth = function() {
return innerWidth;
};
instance.innerHeight = function() {
return innerHeight;
};
instance.svg = function() {
return svg;
};
instance.render = function() {
innerWidth = width - left - right;
innerHeight = height - top - bottom;
svg = d3.select(element)
.append("svg")
.attr("width", innerWidth + left + right)
.attr("height", innerHeight + top + bottom)
.append("g")
.attr("transform", "translate(" + left + ", " + top + ")");
}
return instance;
}
var mySvg = marcon();
mySvg.top(20)
.left(10)
.right(10)
.bottom(20)
.height(200)
.width(200)
.element("body")
.render();
var rect = mySvg.svg()
.append("rect")
.attr("width", mySvg.innerWidth())
.attr("height", mySvg.innerHeight())
.style("fill", "teal");
console.log("The height is " + mySvg.height())
&#13;
svg {
background-color: tan;
}
&#13;
<script src="https://d3js.org/d3.v4.min.js"></script>
<div class="testDiv"></div>
&#13;
答案 1 :(得分:2)
有几种不同的方式来完成你所追求的目标。首先,您应该使用d3
阅读有关可重用性的优秀tutorial。将这些想法与您的代码结合起来会是这样的:
<!DOCTYPE html>
<html>
<head>
<script data-require="d3@4.0.0" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<script>
function marcon() {
var top = 0,
bottom = 0,
left = 0,
right = 0,
width = 900,
height = 600,
svg;
function self(selection) {
var w = width - left - right,
h = height - top - bottom;
svg = selection.append("svg")
.attr("width", width + left + right)
.attr("height", height + top + bottom)
.append("g")
.attr("transform", "translate(" + left + ", " + top + ")");
}
self.top = function(value) {
if (!arguments.length) return top;
top = value;
return self;
};
self.bottom = function(value) {
if (!arguments.length) return bottom;
bottom = value;
return self;
};
self.left = function(value) {
if (!arguments.length) return left;
left = value;
return self;
};
self.right = function(value) {
if (!arguments.length) return right;
right = value;
return self;
};
self.width = function(value) {
if (!arguments.length) return width;
width = value;
return self;
};
self.height = function(value) {
if (!arguments.length) return height;
height = value;
return self;
};
self.svg = function(value){
if (!arguments.length) return svg;
svg = value;
return self;
}
return self;
}
var m = marcon()
.width(100)
.height(100)
.top(50)
.left(50);
d3.select('body')
.call(m);
m.svg()
.append("text")
.text("Hi Mom!");
</script>
</body>
</html>