使用 Velocity.js 从 URL 渲染 SVG 动画

Posted

技术标签:

【中文标题】使用 Velocity.js 从 URL 渲染 SVG 动画【英文标题】:Render SVG from URL for animation with Velocity.js 【发布时间】:2018-02-18 06:05:41 【问题描述】:

我正在构建一个界面来预览应用于 SVG 的动画。我正在尝试使用 React 中的 Velocity.js 库来定位 SVG 的内部动画路径。我正在使用create-react-app。

我可以将 .svg 文件拖放到 react-dropzone 输入中,该输入提供带有 File 对象的回调。我可以将File 对象转换为base64 编码的DataURL,然后我可以将其提供给<object> 标签。这会使用完整的扩展 xml 标记呈现 SVG。

return (
    <object style=
        width: '100%'
    
    id=`svg-$uuid` 
    type="image/svg+xml" data=dataURL
/>)

任何使用 javascript 访问 SVG 的 contentDocument 的尝试(为了将 gpath 元素直接定位为动画)都会导致以下错误:

document.getElementById('svg-665790ae-2a36-446e-9ea9-856442e8b1dc').contentDocument

Uncaught DOMException: Failed to read the 'contentDocument' property from 'htmlObjectElement': 
Blocked a frame with origin "http://localhost:3000" from accessing a cross-origin frame.

我正在开发本地开发环境,在 localhost:3000 上为 React 应用程序提供服务。

作为一种可能的解决方法,我将有问题的 SVG 上传到远程 AWS S3 存储桶。然后我通过远程 URL 检索 SVG,并尝试以某种方式呈现它。我尝试了以下方法:

React SVG &lt;use&gt; tag

<svg>
     <use xlinkHref=url></use>
</svg>

这会产生以下标记,但没有可见的 SVG:

<svg>
    <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="https://s3.amazonaws.com/.../example.svg">
    </use>
</svg>

&lt;object&gt;标签

<object
    style=
        width: '100%',
    
    id=`svg-$uuid` type="image/svg+xml" data=url
/>

这会导致以下标记,没有可见的 SVG,并导致浏览器立即将 SVG 作为文件下载。

<object id="svg-..." type="image/svg+xml" data="https://s3.amazonaws.com/.../example.svg" style="width: 100%;"></object>

react-inlinesvg库

此库发出 XHR 请求以检索 SVG,然后将其嵌入到 DOM 中。

<Isvg src=url/>

这会导致以下错误:

XMLHttpRequest cannot load https://s3.amazonaws.com/.../example.svg. 
No 'Access-Control-Allow-Origin' header is present on the requested resource. 
Origin 'http://localhost:3000' is therefore not allowed access.

SVGInjector

首先,我使用 SVG url 安装了一个简单的 &lt;img&gt; 标签:

return (
    <img
        ref=node => this.testSVG = node
        src=url id="svg" type="image/svg+xml" />
)

这也会导致上述XMLHttpRequest 错误。尝试使用节点ref(即SVGInjector(this.testSVG))或以这种方式从componentDidMount 调用SVGInjector

const el = document.getElementById('svg');
SVGInjector(el);

导致警告消失,但只显示损坏的图像标签。

任何帮助解决这些CORS 警告或有关在 React 中为动画目的将 SVG 嵌入 DOM 的正确方法的指导,将不胜感激。也许我需要做的是通过服务器下载图像,并暂时直接从服务器文件系统提供它,例如,从/public 文件夹。这不是我的首选方法,因为我已经在使用 AWS S3 进行图像托管。

【问题讨论】:

如果您控制您的代码尝试跨域加载图像的服务器 (https://s3.amazonaws.com/.../example.svg),则需要将该服务器配置为包含 Access-Control-Allow-Origin 响应标头它为这些图像提供服务。如果你不控制那个服务器,那么你必须使用某种代理——或者是你在自己的后端设置的东西,或者是一个开放的 CORS 代理。请参阅***.com/a/43881141/441757 答案中的如何使用 CORS 代理解决“No Access-Control-Allow-Origin 标头”问题部分,例如代码+说明 谢谢!这似乎成功了。我现在可以使用 react-inlinesvg 组件来渲染 SVG。我关注 this post 并打开了我的 AWS S3 CORS。我将尝试删除标头以查看最佳配置。 【参考方案1】:

答案是在 AWS S3 控制台中启用 CORS。见***.com/questions/17533888/s3-access-control-allow-origin-header。 CORS配置似乎默认没有启用,所以我必须保存它才能使其生效。

<!-- Sample policy -->
<CORSConfiguration>
    <CORSRule>
        <AllowedOrigin>*</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <AllowedHeader>Authorization</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

感谢sideshowbarker 的推荐。正如他所提到的,如果您从另一个域提供图像,而您无权访问,则可能需要使用代理。请参阅***.com/a/43881141/441757,在如何使用 CORS 代理解决“No Access-Control-Allow-Origin header”问题部分下,了解详细信息。

【讨论】:

以上是关于使用 Velocity.js 从 URL 渲染 SVG 动画的主要内容,如果未能解决你的问题,请参考以下文章

vue里面使用Velocity.js

Web高性能动画及渲染原理CSS动画和JS动画

如何在悬停中使用velocity.js?

利用velocity.js将svg动起来

为 CSS/JS/jQuery 动画使用 Velocity.js 或 Transit.js?

聊聊JS动画库:Velocity.js