有時您需要在轉換「開始」和「結束」事件回調中進行計算密集型工作(轉換需要),這可能需要很長時間才能完成,即轉換開始時(或下一個鏈接轉換開始時爲「結束「事件),時間已經超過了轉換開始時間,導致轉換跳轉。如何適應d3.transition回調中的長計算時間?
這個問題可以在下面看到。第一個和第二個動畫過渡從其開始值直接跳到半完成。
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="//d3js.org/d3-selection.v1.min.js"></script>
<!-- This script is d3-timer.min.js with https://github.com/d3/d3-timer/pull/28 that fixes https://github.com/d3/d3-timer/issues/27 -->
<script>!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n(t.d3=t.d3||{})}(this,function(t){"use strict";function n(){return h||(x(e),h=v.now()+y)}function e(){h=0}function o(){this._call=this._time=this._next=null}function i(t,n,e){var i=new o;return i.restart(t,n,e),i}function r(){n(),++_;for(var t,e=f;e;)(t=h-e._time)>=0&&e._call.call(null,t),e=e._next;--_}function u(){h=(d=v.now())+y,_=m=0;try{r()}finally{_=0,c(),h=0}}function l(){var t=v.now(),n=t-d;n>w&&(y-=n,d=t)}function c(){for(var t,n,e=f,o=1/0;e;)e._call?(o>e._time&&(o=e._time),t=e,e=e._next):(n=e._next,e._next=null,e=t?t._next=n:f=n);s=t,a(o)}function a(t){_||(m&&(m=clearTimeout(m)),t-h>24?(t<1/0&&(m=setTimeout(u,t-v.now()-y)),p&&(p=clearInterval(p))):(p||(d=v.now(),p=setInterval(l,w)),_=1,x(u)))}var f,s,_=0,m=0,p=0,w=1e3,d=0,h=0,y=0,v="object"==typeof performance&&performance.now?performance:Date,x="object"==typeof window&&window.requestAnimationFrame?window.requestAnimationFrame.bind(window):function(t){setTimeout(t,17)};o.prototype=i.prototype={constructor:o,restart:function(t,e,o){if("function"!=typeof t)throw new TypeError("callback is not a function");o=(null==o?n():+o)+(null==e?0:+e),this._next||s===this||(s?s._next=this:f=this,s=this),this._call=t,this._time=o,a()},stop:function(){this._call&&(this._call=null,this._time=1/0,a())}};t.now=n,t.timer=i,t.timerFlush=r,t.timeout=function(t,n,e){var i=new o;return n=null==n?0:+n,i.restart(function(e){i.stop(),t(e+n)},n,e),i},t.interval=function(t,e,i){var r=new o,u=e;return null==e?(r.restart(t,e,i),r):(e=+e,i=null==i?n():+i,r.restart(function n(o){o+=u,r.restart(n,u+=e,i),t(o)},e,i),r)},Object.defineProperty(t,"__esModule",{value:!0})});</script>
<script src="//d3js.org/d3-dispatch.v1.min.js"></script>
<script src="//d3js.org/d3-interpolate.v1.min.js"></script>
<script src="//d3js.org/d3-color.v1.min.js"></script>
<script src="//d3js.org/d3-ease.v1.min.js"></script>
<script src="//d3js.org/d3-transition.v1.min.js"></script>
<script src="//d3js.org/d3-scale.v1.min.js"></script>
<script src="//d3js.org/d3-zoom.v1.min.js"></script>
<div style="text-align: center;"></div>
<script>
var start = Date.now();
function elapsed() {
return Date.now() - start;
}
function waste(time) {
var t0 = Date.now();
while (Date.now() - t0 < time)
;
}
var svg = d3.select("div").append("svg")
.attr("width", 800)
.attr("height", 500);
var g = svg.append("g");
var start1Waste = 2000;
var end1Waste = 2000;
var start2Waste = 0;
var end2Waste = 0;
g.selectAll("rect")
.data([10, 100, 200])
.enter()
.append("rect")
.attr("width", d => d)
.attr("height", d => d)
.attr("fill", "none")
.attr("stroke", "black")
var rect = g.append("rect")
.attr("width", 10)
.attr("height", 10)
.attr("fill", "#d62728")
.transition()
.delay(2000)
.duration(4000)
.ease(d3.easeLinear)
.attr("width", 100)
.attr("height", 100)
.on("start", function() {
console.log('Start event 1', elapsed()/1000);
waste(start1Waste);
console.log('Start event 1 returning', elapsed()/1000);
})
.on("end", function() {
console.log('End event 1', elapsed()/1000);
waste(end1Waste);
console.log('End event 1 returning', elapsed()/1000);
})
.transition()
.attr("width", 200)
.attr("height", 200)
.attr("fill", "#1f77b4")
.on("start", function() {
console.log('Start event 2', elapsed()/1000);
waste(start2Waste);
console.log('Start event 2 returning', elapsed()/1000);
})
.on("end", function() {
console.log('End event 2', elapsed()/1000);
waste(end2Waste);
console.log('End event 2 returning', elapsed()/1000);
})
</script>
注:一個bug in d3-timer是fixed, 但尚未發佈寫這篇文章的時候,要求這個例子中使用非官D3定時器.min.js。
一)不要在一個網絡工作者的計算密集型任務。 b)使用SMIL代替動畫,瀏覽器將自動處理所有時間並解決任何滯後問題。 –
@RobertLongson a)我自己想過一個web工作者,但是在這個例子中,如果轉換需要計算結果,那麼如何使用它呢? b)不會使用SMIL意味着放棄使用d3.transition?或者他們可以合併? – magjac
@RobertLongson我已經闡明瞭計算需要通過 – magjac