我经常使用d3.js并且最近一直在考虑他们的linearScale函数。
它允许你这样做:
var x = d3.scaleLinear()
.domain([10, 130])
.range([0, 960]);
x(20); // 80
x(50); // 320
据我所知:
我不需要知道有关d3如何实现这一点的任何具体内容,d3只是我想到的第一个允许我这样做的API示例。
我有兴趣在javascript中实现类似的东西,并希望以最简单的形式知道必要的设计模式。
我曾尝试查看d3的源代码,但是有很多额外的功能,而且它分成了多个文件 - 这让我很难找到我正在寻找的东西,特别是当我不喜欢的时候我知道那是什么。任何帮助将不胜感激。
答案 0 :(得分:2)
首先要注意的是,JavaScript函数只是可以附加属性的对象,这些属性可以包含其他函数。
基本上scaleLinear()
返回一个函数,该函数又用作API对象。
附加到API对象/函数的函数用于获取或设置封装闭包创建的内部状态。
附加到API对象/函数的函数通常返回API实例以允许链接调用。
希望下面的例子能说明如何开发这样的东西。
function Greet() {
var person = '';
var message = 'Hello';
var api = function () {
console.log(message + ' ' + person);
return api;
};
api.person = function (value) {
// if nothing is passed into function act as getter
if (!arguments.length) return person;
// otherwise set the value
person = value;
// return the api function for more chaining or calling
return api;
};
api.message = function (value) {
if (!arguments.length) return message;
message = value;
return api;
};
return api;
}
var greeter = Greet().person('Daniel');
greeter(); // 'Hello Daniel'
greeter.message('Whaddup').person('Martha')(); // 'Whaddup Martha'
我只记得Mike Bostock(d3的创建者)撰写了一篇博客文章,他详细介绍了这种模式: https://bost.ocks.org/mike/chart/
答案 1 :(得分:0)
我发现this tutorial非常实用
我有这种方法的样板
function getChart(params) {
// exposed variables
var attrs = {
svgWidth: 400,
svgHeight: 400,
marginTop: 5,
marginBottom: 5,
marginRight: 5,
marginLeft: 5,
data: null
};
/*############### IF EXISTS OVERWRITE ATTRIBUTES FROM PASSED PARAM ####### */
var attrKeys = Object.keys(attrs);
attrKeys.forEach(function (key) {
if (params && params[key]) {
attrs[key] = params[key];
}
})
//innerFunctions
var updateData;
//main chart object
var chart = function (selection) {
selection.each(function () {
//calculated properties
var calc = {}
calc.chartLeftMargin = attrs.marginLeft;
calc.chartTopMargin = attrs.marginTop;
calc.chartWidth = attrs.svgWidth - attrs.marginRight - calc.chartLeftMargin;
calc.chartHeight = attrs.svgHeight - attrs.marginBottom - calc.chartTopMargin;
//drawing
var svg = d3.select(this)
.append('svg')
.attr('width', attrs.svgWidth)
.attr('height', attrs.svgHeight)
// .attr("viewBox", "0 0 " + attrs.svgWidth + " " + attrs.svgHeight)
// .attr("preserveAspectRatio", "xMidYMid meet")
var chart = svg.append('g')
.attr('width', calc.chartWidth)
.attr('height', calc.chartHeight)
.attr('transform', 'translate(' + (calc.chartLeftMargin) + ',' + calc.chartTopMargin + ')')
// smoothly handle data updating
updateData = function () {
}
});
}
//exposed variable funcs
chart.data = function (value) {
if (!arguments.length) return attrs.data;
attrs.data = value;
if (typeof updateData === 'function') {
updateData();
}
return chart;
}
chart.width = function (value) {
if (!arguments.length) return attrs.svgWidth;
attrs.svgWidth = value;
return chart;
}
chart.height = function (value) {
if (!arguments.length) return attrs.svgHeight;
attrs.svgHeight = value;
return chart;
}
return chart;
}
然后你可以像这样调用图表