为什么不应用CSS转换?

时间:2015-06-16 12:35:59

标签: javascript html css knockout.js

我已经使用浮动的divs构建了一个小的堆叠条形图,其下面使用knockout绑定到某些数据。我希望能够做的是在数据发生变化时动画显示这些堆栈大小的变化。

我已经设法在一般情况下这样做了,所以我得到的4个小节,其中3个正确过渡。问题是我的最后一栏似乎忽略了过渡并立即重新调整大小,我无法理解为什么。这是状态之前/期间/之后的图片:

enter image description here

我定义此转换的方式只是通过css

-webkit-transition: width 1s;
transition: width 1s;

条形的宽度是计算值,计算项目的百分比,因此每个条形的宽度应定义为百分比。虽然红色条的计算方式与其他3条不同,但我不明白为什么会影响转换。

我觉得很奇怪,例如,如果我通过开发者控制台修改宽度,那么条形图就会正确生成动画。我想知道是否有人可以建议为什么会出现这种情况?

var vm = (function generateModel() {
    var data = {
        name: "Sign-off",
        id: "XX",
        values: [{ text: "Signed-off", count: 150, color: "#5fb5cc" }, 
                 { text: "Submitted", count: 90, color: "#75d181" }, 
                 { text: "Not Submitted", count: 75, color: "#f8a25b" }
                ],
        aggregates: {
            count: 650
        }
    };

    // Create a view model directly from the data which we will update
    var vm = ko.mapping.fromJS(data);

    // Add a computed value to calculate percentage
    vm.values().forEach(function (d) {
        d.percentage = ko.computed(function () {
            return d.count() / vm.aggregates.count() * 100;
        });
    });
    
    // Create a 
    vm.allValues = ko.computed(function() {
        var values = [];
        var count = 0;
        var total = vm.aggregates.count();
        
        debugger;
        
        // Add each of these results into those that will be returned
        vm.values().forEach(function(d) { 
           values.push(d); 
            count += d.count();
        });
        
        // Create an other category for everything else
        values.push({
            text: ko.observable("Other"),
            count: ko.observable(total - count),
            percentage: ko.observable((total - count) / total * 100),
            color: ko.observable("#ff0000")
        });
        
        return values;
    });

    return vm;
})();

ko.applyBindings(vm);

setTimeout(function() {
   vm.values()[0].count(90);
    vm.values()[1].count(40);
    vm.values()[2].count(35);
    vm.aggregates.count(3550);
}, 3000);
body {
    background: rgb(40, 40, 40);
}
.spacer {
    height: 230px;
}
.cards {
    float: right;
}
/* Small Card */
 .card {
    margin-bottom: 3px;
    background: white;
    border-radius: 3px;
    width:398px;
    float: right;
    clear: both;
    min-height: 100px;
    padding: 10px 5px 15px 5px;
    font-family:'Open Sans', Arial, sans-serif;
}
.title {
    color: rgb(105, 161, 36);
    font-size: 16px;
}
.states {
    padding-top: 10px;
}
.state {
    font-size: 12px;
    color: rgb(67, 88, 98);
    padding: 0px 5px 2px 5px;
    clear: both;
}
.circle {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    float: left;
    margin: 1px 5px 5px 0px;
}
.value {
    float: right;
}
.graph {
    padding: 10px 5px 0px 5px;
}
.bar {
    float: left;
    height: 10px;
    -webkit-transition: width 10s;
    transition: width 10s;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.js"></script>
<div class="card">
    <div class="content">
        <div class="graph" data-bind="foreach: allValues">
            <div class="bar" data-bind="style: { background: color, width: percentage() + '%' }"/>
        </div>
    </div>
</div>

1 个答案:

答案 0 :(得分:4)

由于前三个是基于不会改变的对象引用,因此淘汰赛将保留已呈现的实际<div>

对于最终栏,每次评估allValues时,它都会将一个全新的对象推入返回的数组中。我认为,因为knockout将其视为一个新对象,它会从头开始重新呈现div,而不是更新现有绑定。

您需要稍微修改模型以保存最终值的实际对象,以便您可以以相同的方式更新其上的可观察对象。

这是一个使用静态对象的固定版本,用于&#34;其他&#34;值:

&#13;
&#13;
var vm = (function generateModel() {
    var data = {
        name: "Sign-off",
        id: "XX",
        values: [{ text: "Signed-off", count: 150, color: "#5fb5cc" }, 
                 { text: "Submitted", count: 90, color: "#75d181" }, 
                 { text: "Not Submitted", count: 75, color: "#f8a25b" }
                ],
        aggregates: {
            count: 650
        }
    };

    // Create a view model directly from the data which we will update
    var vm = ko.mapping.fromJS(data);

    // Add a computed value to calculate percentage
    vm.values().forEach(function (d) {
        d.percentage = ko.computed(function () {
            return d.count() / vm.aggregates.count() * 100;
        });
    });
    
    //Create a static "others" object
    vm.other = {
        text: ko.observable("Other"),
        count: ko.computed(function() { 
            var total = vm.aggregates.count();
            var count = 0;
            vm.values().forEach(function(d) { count += d.count(); });
            return total - count;
        }),
        percentage: ko.computed(function(d, b) {
            var total = vm.aggregates.count();
            var count = 0;
            vm.values().forEach(function(d) { count += d.count(); });
            return (total - count) / total * 100;
        }),
        color: ko.observable("#ff0000")
    };
  
    // Create a 
    vm.allValues = ko.computed(function() {
        var values = [];
        var count = 0;
        var total = vm.aggregates.count();
        
        debugger;
        
        // Add each of these results into those that will be returned
        vm.values().forEach(function(d) { 
           values.push(d); 
            count += d.count();
        });
              
        // and push static object in instead of creating a new one
        values.push(vm.other);
        
        return values;
    });

    return vm;
})();

ko.applyBindings(vm);

setTimeout(function() {
   vm.values()[0].count(90);
    vm.values()[1].count(40);
    vm.values()[2].count(35);
    vm.aggregates.count(3550);
}, 3000);
&#13;
body {
    background: rgb(40, 40, 40);
}
.spacer {
    height: 230px;
}
.cards {
    float: right;
}
/* Small Card */
 .card {
    margin-bottom: 3px;
    background: white;
    border-radius: 3px;
    width:398px;
    float: right;
    clear: both;
    min-height: 100px;
    padding: 10px 5px 15px 5px;
    font-family:'Open Sans', Arial, sans-serif;
}
.title {
    color: rgb(105, 161, 36);
    font-size: 16px;
}
.states {
    padding-top: 10px;
}
.state {
    font-size: 12px;
    color: rgb(67, 88, 98);
    padding: 0px 5px 2px 5px;
    clear: both;
}
.circle {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    float: left;
    margin: 1px 5px 5px 0px;
}
.value {
    float: right;
}
.graph {
    padding: 10px 5px 0px 5px;
}
.bar {
    float: left;
    height: 10px;
    -webkit-transition: width 10s;
    transition: width 10s;
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.js"></script>
<div class="card">
    <div class="content">
        <div class="graph" data-bind="foreach: allValues">
            <div class="bar" data-bind="style: { background: color, width: percentage() + '%' }"/>
        </div>
    </div>
</div>
&#13;
&#13;
&#13;