使用React和Ruffle播放Flash

用途

当我们想在React等SPA中使用遗产Flash文件(*.swf)时!
显然,不能依赖于Flash Player。
React + Ruffle + *.swf 或者前端Web框架 + Ruffle + *.swf

直到公开为止

自从Adobe完全终止支持Flash Player后已经很久了。
那是在2020年12月31日发生的事情…。

播放遗产 Flash 文件(*.swf)的方法仍然有需求。
可能需要视频内的可点击部分,
不能简单地将视频转换为MP4。
但是,从头开始使用HTML5+CSS3动画制作也很麻烦。

因此,我尝试验证了Ruffle和swf2js。
如果是静态页面,只需查看Ruffle的官方文档即可轻松实现。
但是对于动态页面或SPA,情况就不那么简单了。

    • URL が切り替わると再生されない!

 

    • Rust から自分でコンパイルすればいいらしい?

 

    wasm-loader が要るらしいけど、webpack なの? create-react-app なの?

这种感觉非常混乱。

我正在寻找再生的方法,并找到了一个相当简单的解决方案,现在向你介绍。

解决模式,办法,措施

当SPA内的内容被绘制时,会动态地触发自定义事件。
在该自定义事件中,开始播放Flash。

关键词如下:

    • componentDidMount

 

    • dispatchEvent

 

    • addEventListener

 

    CustomEvent

以下的例子使用了 React + TypeScript。 但我认为在 React + JavaScript 或其他前端 Web 框架的情况下,只需做出少量修改即可。

只有一个选项可以用中文本地语言改写:
※ 在ruffle.js中加载*.wasm文件。由于wasm文件的尺寸较大,这种方法不适合希望进行优化的人。这种情况下,从Rust编译可能更好。

这个方法是根据Ruffle官方文档中的描述,是建立在Website Self Hosted的基础上的方法。不需要使用Rust开发环境。

组成

┣━public
┃    ┣━ flash
┃    ┃    ┗━ flash
┃    ┃        ┗━ legacy.swf
┃    ┗━ ruffle
┃         ┗━ ruffle-nightly-2021_05_17-web-selfhosted
┃             ┣━ ???.wasm
┃             ┣━ ...
┃             ┗━ ruffle.js
┗━src
    ┣━ components
    ┃    ┣━ fixed_mainnav.tsx
    ┃    ┣━ header.tsx
    ┃    ┣━ main.tsx
    ┃    ┗━ maincontent.tsx
    ┣━ index.html
    ┗━ index.tsx

当 JSX 在 maincontent.tsx 中被加载时,会每次播放 legacy.swf。

代码 (Mandarin: “daima”)

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
  <title>React App</title>
  <script src="%PUBLIC_URL%/ruffle/ruffle-nightly-2021_05_17-web-selfhosted/ruffle.js"></script>
</head>
<body>
  <div id="root"></div>
</body>
<script>
  var config = {
    // Options affecting the whole page
    "publicPath": "Failed to load the video!",
    "polyfills": true,
    // Options affecting files only
    "autoplay": "true",
    "unmuteOverlay": "hidden",
    "backgroundColor": null,
    "letterbox": "fullscreen",
    "warnOnUnsupportedContent": true,
    "contextMenu": false,
    "upgradeToHttps": window.location.protocol === "https:",
    "logLevel": "error",
  };

  function loadflash(elementId,flashUrl) {
    const ruffle = window.RufflePlayer.newest();
    const player = ruffle.createPlayer();
    const container = document.getElementById(elementId);
    container.appendChild(player);
    player.config = config;
    player.load(flashUrl);
  }
  function loadflash001() {
    loadflash('flash001','%PUBLIC_URL%/flash/legacy.swf');
  }
  window.addEventListener("playflash", loadflash001);
  window.addEventListener("load", loadflash001);
</script>

</html>

在标签内,我们通过以下方式加载了ruffle.js。

  <script src="%PUBLIC_URL%/ruffle/ruffle-nightly-2021_05_17-web-selfhosted/ruffle.js"></script>

loadflash是一个播放Flash的函数。

最終目標是在load事件和playflash事件中播放Flash。为什么需要注册在load事件上呢?因为无法通过直接输入URL来触发playflash事件。如果有人能详细验证这方面内容并留下评论,我会很开心。

我尝试直接为loadflash添加了addEventListener,但是发现在load事件发生时也会同时触发playflash事件。因此,我使用loadflash001函数,故意进行两层组合。

import React from 'react';
import ReactDOM from 'react-dom';
import './index.sass';
import reportWebVitals from './reportWebVitals';
import MainApp from "./components/main";
import HeaderApp from "./components/header";
import FooterApp from "./components/footer";
import { createBrowserHistory } from "history"
import { Router } from 'react-router';

const history = createBrowserHistory({ basename: '/new_web' });
ReactDOM.render(
  <React.StrictMode>
    <Router history = {history}>
      <HeaderApp></HeaderApp>
      <MainApp></MainApp>
      <FooterApp></FooterApp>
      </Router>
  </React.StrictMode>,
  document.getElementById('root')
);
reportWebVitals(console.log);
import React from 'react';
import { Route, Switch } from 'react-router-dom';
import OutlineApp from './outline';
import MainContentApp from './maincontent';

class MainApp extends React.Component {
    render() {
        return (
            <main id="wrap_main">
                <div id="sidearea"></div>
                <div id="wrap_contents">
                    <Switch>
                        <Route exact path="/" component={MainContentApp} />
                        <Route exact path="/outline/" component={OutlineApp} />
                        <Route render={() => <p>NotFound</p>} />
                    </Switch>
                </div>
                <div id="main-right-spacer"></div>
            </main >
        );
    }
}
export default MainApp;

在上述的main.tsx文件中,

<Route exact path="/" component={MainContentApp} />
<Route exact path="/outline/" component={OutlineApp} />

有一部分是这样的。在这里,当URL转移到/时,将加载MainContentApp。
那里有一个想要播放Flash的标签id=’flash001’。

然而,当URL转到/outline/时,将加载OutlineApp而不是MainContentApp。
因此,标签id=’flash001’会消失一次。

当URL再次转换为/时,MainContentApp将再次加载。
tag id=’flash001’将再次出现。

在这种情况下,只使用 window.addEventListener(“load”, func) 是无法播放 Flash 的。
这是因为 load 事件只会在初次加载 DOM 时才会发生。

import React from 'react';
let FlashEvent = new CustomEvent('playflash', { bubbles: true });

class MainContentApp extends React.Component {
    componentDidMount() {
        window.dispatchEvent(FlashEvent);
    }
    render() {
        return (
            <React.StrictMode>
                <div id="flash001"></div>
            </React.StrictMode>
        );
    }
}
export default MainContentApp;

在maincontent.tsx中,存在着

。在这里将加载Flash。

此外,在maincontent.tsx中的第2行中,我们声明了一个名为playflash的事件,如下所示。

let FlashEvent = new CustomEvent('playflash', { bubbles: true });

当MainContentApp组件被挂载后,

    componentDidMount() {
        window.dispatchEvent(FlashEvent);
    }

通过这样做,会触发FlashEvent。
这将激活index.html中准备好的playflash事件监听器。

import React from 'react';
import { NavLink } from 'react-router-dom';
import FixedMainNavApp from "./fixed_mainnav";

class HeaderApp extends React.Component {
    render() {
        return (
            <React.StrictMode>
                <header id="wrap_header">
                    <div id="wrap_logo">
                        <a href="/">
                            <img id="mainlogo" alt="株式会社logo" />
                        </a>
                    </div>
                    <nav id="wrap_gmenu">
                        <ul>
                            <FixedMainNavApp />
                        </ul>
                    </nav>
                </header>
            </React.StrictMode>
        );
    }
}
export default HeaderApp;

在上述的header.tsx文件中,通过FixedMainNavApp组件加载导航链接。

import React from 'react';
import { Link } from 'react-router-dom';

class FixedMainNavApp extends React.Component {
    render() {
        return (
            <React.StrictMode>
                    <li><Link to="/">ホーム</Link></li>
                    <li><Link to="/outline/">会社概要</Link></li>
                    <li><Link to="/digital/">デジタル事業</Link></li>
                    <li><Link to="/recruit/">リクルート</Link></li>
                    <li><Link to="/sitemap">サイトマップ</Link></li>
            </React.StrictMode>
        );
    }
}
export default FixedMainNavApp;

当用户在fixed_mainnav.tsx中点击Link标签时,将进行URL跳转。

整理/总结

抛开负面遗产,才能获得幸福。 加油!

bannerAds