我正在尝试删除Google swiffy(v 5.2.0)动画,然后在以后阅读它。
就运行动画而言,似乎没有任何问题,但代码会触发错误:TypeError:无法重新定义属性:Animation_fla.MainTimeline,此时影片中的所有AS3都停止工作。这似乎是因为destroy方法没有在swiffy运行时中删除对AS3代码的引用。我花了一些时间试图逐步完成代码,但这是非常难以理解的。
下面是我正在使用swiffy执行的所有操作的删除版本 - 在调用destroy之后再次调用init将触发此TypeError。我试图重新初始化swiffy运行时本身,但这会导致类似的错误。
var stage;
function init() {
stage = new swiffy.Stage(domElement, swiffyJson);
stage.start();
}
function destroy() {
stage.destroy();
stage = null;
}
答案 0 :(得分:1)
我提出的唯一解决方案是非常可怕的黑客攻击。看起来Swiffy并不想在它们被摧毁后重新制作动画。我已经取得了一些成功,将Swiffy从DOM中分离出来但保留了它在内存中的引用。然后,我不得不破解运行时以启用暂停和重新启动。然后我可以重新连接原始的Swiffy而不必破坏它。这是在通过jsbeautifier.org运行运行时从https://www.gstatic.com/swiffy/v5.2/runtime.js下载的v5.2.0中
在M.releaseCapture
函数之后的第5640行附近,我添加了以下函数:
M.hackPause = function (bool) {
if(this.hackPaused === bool) return;
if(this.hackPaused) {
bi(ef(this.qh.yl, this.qh));
}
this.hackPaused = bool;
};
围绕第7137行,将AK[I].yl
函数替换为以下内容:
Ak[I].yl = function () {
if (this.bh) {
var a = Date.now();
a >= this.Mf && (this.tl.ei(), this.Mf += (s[Xb]((a - this.Mf) / this.sl) + 1) * this.sl);
this.tl.lc();
if(!this.tl.hackPaused) {
bi(ef(this.yl, this))
}
}
};
这样做会阻止requestAnimationFrame或setTimeout触发,从而有效地暂停动画。
我也尝试在运行时中公开gotoAndStop函数,但我无法在代码中找到范围。与此同时,使用此帖子中的黑客 - Is it possible to pause/resume/manipulate a swiffyobject from JS?,我们可以通过向Flash电影添加输入帧事件并测试Flashvars中的更改,以蛮力方法执行此操作。以下是我们用于动画的文档类。值得注意的是,Swiffy似乎并不喜欢从同一个基类扩展的AS3类,它抛出同样的不能重新定义属性错误,因此我们在文档中重复了此处的代码每个Flash动画的类。我还有一个方法,允许从AS3调度事件到一个名为onSwiffyEvent的javascript函数:
package {
import flash.display.MovieClip;
import flash.net.URLRequest;
import flash.net.navigateToURL;
import flash.events.Event;
import flash.utils.setTimeout;
public class BaseAnimation extends MovieClip {
private var _request:URLRequest;
private var _pageName:String;
private var _movieName:String;
public function BaseAnimation() {
_request = new URLRequest();
_pageName = getFlashVar('pageName');
_movieName = getFlashVar('movieName');
addEventListener(Event.ENTER_FRAME, jsListen);
}
private function getFlashVar(name:String):String {
var flashVar:String = stage.loaderInfo.parameters[name] || '';
stage.loaderInfo.parameters[name] = '';
return flashVar;
}
public function dispatchJSEvent(eventName:String, param:String = ''):void {
_request.url = "javascript:onSwiffyEvent('" + eventName + "', '" + param + "', '" + _movieName + "', '" + _pageName + "');";
navigateToURL(_request, "_self");
}
private function jsListen(e:Event):void {
var mode:String = getFlashVar('mode');
if(mode.length) {
switch(mode) {
case 'stop':
stop();
break;
case 'play':
play();
break;
case 'gotoStart':
gotoAndStop('start');
break;
}
}
}
}
}
Swiffy似乎也不喜欢gotoAndStop(0)所以我必须设置一个框架标签“开始”#39在动画的第一帧。
有了这些可怕的hackery,我们就能够删除并重新启动Swiffy动画。我们发现的唯一问题是分离和重新附加导致嵌入式SVG字体出现问题,我们最终将所有文本转换为大纲。以上使用如下:
你可以像这样在漂亮的舞台上调用它:
var stage = new swiffy.Stage(domObject, swiffyObj);
stage.start();
// when reading to remove this element from the DOM do the following:
stage.setFlashVars('mode=gotoStart');
setTimeout(function () {
// timeout is required to ensure that the enterframe listener has time to run
stage.hackPause(true); // paused animation
}, 100);
// you can then remove the containing div from the DOM, but retain it in memory
// after you reattach the div to the DOM, ensuring we've kept hold of our stage variable in memory, you can restart it like this:
stage.hackPause(false); // resumes javascript requestAnimationFrame
stage.setFlashVars('mode=play'); // resumes flash animation
希望这对某人有所帮助,但我也非常希望Google开始向Swiffy运行时公开某种JS API或ExternalInterface,以便让我们更好地控制什么是非常棒的工具。
答案 1 :(得分:0)
尝试在将swiffy对象传递给swiffy.Stage()之前创建swiffyobject的副本。 Swiffy正在实例化时修改对象,因此使用副本只需在destroy()
之后重新创建