Use timeout-based animation for hourglasses

CSS animations are convenient but costly if you have hundreds of them.

Fixes #945
This commit is contained in:
lilia 2016-10-30 16:53:17 +09:00
parent c0a160b1dd
commit 35270dbbb4
3 changed files with 17 additions and 27 deletions

View file

@ -29,14 +29,20 @@
templateName: 'hourglass',
className: 'timer',
initialize: function() {
this.update();
},
update: function() {
if (this.timeout) {
clearTimeout(this.timeout);
this.timeout = null;
}
if (this.model.isExpiring()) {
this.render();
var totalTime = this.model.get('expireTimer') * 1000;
var remainingTime = this.model.msTilExpire();
var elapsed = (totalTime - remainingTime) / totalTime;
this.$('.sand')
.css('animation-duration', remainingTime*0.001 + 's')
.css('transform', 'translateY(' + elapsed*100 + '%)');
this.$('.sand').css('transform', 'translateY(' + elapsed*100 + '%)');
this.timeout = setTimeout(this.update.bind(this), totalTime / 100);
this.$el.css('display', 'inline-block');
}
return this;
@ -201,7 +207,10 @@
}
},
renderExpiring: function() {
new TimerView({ model: this.model, el: this.$('.timer') });
if (!this.timerView) {
this.timerView = new TimerView({ model: this.model, el: this.$('.timer') });
}
this.timerView.update();
},
render: function() {
var contact = this.model.isIncoming() ? this.model.getContact() : null;

View file

@ -17,13 +17,8 @@
}
.sand {
background: $color;
animation: moveDown steps(100);
animation-fill-mode: forwards;
}
&:after {
@include color-svg('/images/hourglass_empty.svg', $color);
}
@keyframes moveDown {
to { transform: translateY(100%); }
}
}

View file

@ -1538,16 +1538,12 @@ li.entry .error-icon-container {
top: 0;
left: 0; }
.ios .hourglass .sand {
background: #999;
animation: moveDown steps(100);
animation-fill-mode: forwards; }
background: #999; }
.ios .hourglass:after {
-webkit-mask: url("/images/hourglass_empty.svg") no-repeat center;
-webkit-mask-size: 100%;
background-color: #999; }
@keyframes moveDown {
to {
transform: translateY(100%); } }
.android #header {
background-color: #2090ea;
color: white;
@ -1618,16 +1614,11 @@ li.entry .error-icon-container {
top: 0;
left: 0; }
.android .outgoing .hourglass .sand {
background: #999;
animation: moveDown steps(100);
animation-fill-mode: forwards; }
background: #999; }
.android .outgoing .hourglass:after {
-webkit-mask: url("/images/hourglass_empty.svg") no-repeat center;
-webkit-mask-size: 100%;
background-color: #999; }
@keyframes moveDown {
to {
transform: translateY(100%); } }
.android .incoming .hourglass {
display: inline-block;
position: relative;
@ -1645,16 +1636,11 @@ li.entry .error-icon-container {
top: 0;
left: 0; }
.android .incoming .hourglass .sand {
background: #fff;
animation: moveDown steps(100);
animation-fill-mode: forwards; }
background: #fff; }
.android .incoming .hourglass:after {
-webkit-mask: url("/images/hourglass_empty.svg") no-repeat center;
-webkit-mask-size: 100%;
background-color: #fff; }
@keyframes moveDown {
to {
transform: translateY(100%); } }
.android .incoming .bubble .sender, .android .incoming .bubble .content, .android .incoming .bubble .body, .android .incoming .bubble .meta, .android .incoming .bubble a {
color: white; }
.android .incoming .bubble .sender::selection, .android .incoming .bubble .content::selection, .android .incoming .bubble .body::selection, .android .incoming .bubble .meta::selection, .android .incoming .bubble a::selection {