我已经使用浮动的divs
构建了一个小的堆叠条形图,其下面使用knockout
绑定到某些数据。我希望能够做的是在数据发生变化时动画显示这些堆栈大小的变化。
我已经设法在一般情况下这样做了,所以我得到的4个小节,其中3个正确过渡。问题是我的最后一栏似乎忽略了过渡并立即重新调整大小,我无法理解为什么。这是状态之前/期间/之后的图片:
我定义此转换的方式只是通过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>
答案 0 :(得分:4)
由于前三个是基于不会改变的对象引用,因此淘汰赛将保留已呈现的实际<div>
。
对于最终栏,每次评估allValues
时,它都会将一个全新的对象推入返回的数组中。我认为,因为knockout将其视为一个新对象,它会从头开始重新呈现div,而不是更新现有绑定。
您需要稍微修改模型以保存最终值的实际对象,以便您可以以相同的方式更新其上的可观察对象。
这是一个使用静态对象的固定版本,用于&#34;其他&#34;值:
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;