使用Knockout将D3滑块数据绑定

时间:2014-11-12 15:09:14

标签: knockout.js d3.js

我设法创建了一个D3滑块(从之前的一些示例中进行了修改),此刻我试图将其绑定到Knockout。我的最终用例需要同时在屏幕上显示大量滑块,并且能够通过下面的计算引擎修改值 - knockout应该提供一种很好的方法。

我的问题是试图弄清楚如何将对象数据绑定在一起,我计划使用一些自定义绑定,但无法弄清楚如何实际获取我的对象。我的滑块的简短代码示例:

custom.d3.slider = function () {
    var slider = { };
    var value;

    slider.value = function (_) {
        if (!arguments.length) return value;
        _update(_);
        return slider;
    };

    slider.appendTo = function (target) {

         var sliderBar = target.append("g")
            .attr("class", "slider " + cssClass)
            .attr("data-bind", "slide: 0.5")
            .attr("transform", "translate(" + margin.left + ", " + margin.top + ")")
            .call(d3.svg.axis()
                .scale(xScale)
                .tickSize(0) // ensure that end ticks are not displayed
                .ticks([])) // ensure that no ticks are included in the DOM
            .select(".domain") // this is a custom class added by D3
            .select(function () {
                return this.parentNode.appendChild(this.cloneNode(true));
            })
            .attr("class", "inner-bar")
            .select(function () {
                return this.parentNode.appendChild(this.cloneNode(true));
            })
        .attr("class", "fill-bar");

    };

    return slider;
}

所以在此之后我想设置我的自定义绑定,我现在用调试器语句定义了以下绑定,试着看看发生了什么:

ko.bindingHandlers.slide = {
    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        var d = d3.select(element);   
        debugger;
    },
    update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
         var d = d3.select(element);   
        debugger;
    }
};

这让我得到了我认为是D3对象(而不是DOM对象):

enter image description here

我无法弄清楚的问题是,如何从这里实际访问我的slider.value()功能。甚至可能这样做,还是我以错误的方式解决这个问题? JSFiddle example

我已经设法获得了一个解决方案JSFiddle here,但它只是觉得做错的方法,即手动更新视图模型并订阅事件:

slider.callback(function(context, value) {
                        vm.myVal(value);
                        console.log(context.value());
                });
var vm = {
    myVal: ko.observable(0.5)  
};

vm.myVal.subscribe(function(v) { 
   slider.value(v); 
});

1 个答案:

答案 0 :(得分:1)

尝试将滑块的所有逻辑放在slide bindingHandler中。您的init应该实例化一个新的滑块,更新应该更新滑块的值,例如:

ko.bindingHandlers.slide = {
    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        var valueObservable = valueAccessor();
        element.__slider__ = custom.d3.slider()
                    .configure({
                        minimumValue: 0,
                        maximumValue: 1,
                        value: 0.5          
                    })
                    .margin({ top: 20, left: 40})
                    .appendTo(element)
                    .callback(function (context, value) {
                        valueObservable(context.value());
                    });
        // or when you're using jQuery, use the .data function to store the 
        // slider instance: $(element).data('slider', ...);
    },
    update: function(element, valueAccessor) {
        element.__slider__.value(ko.unwrap(valueAccessor()));
    }
};

请参阅http://jsfiddle.net/v8tvkb4j/