我正在构建一个界面来预览应用于SVG的动画。我试图在React中使用Velocity.js库来定位SVG的动画内部路径。我使用create-react-app。
我能够将.svg文件拖放到react-dropzone输入中,该输入提供带有File
对象的回调。我可以将File
对象转换为base64编码的DataURL,然后我可以将其提供给<object>
标记。这使SVG具有完整的扩展xml标记。
return (
<object style={{
width: '100%'
}}
id={`svg-${uuid}`}
type="image/svg+xml" data={dataURL}
/>)
尝试使用javascript访问SVG的contentDocument
(为了直接针对动画定位g
和path
元素)会导致以下错误:
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,并试图以某种方式呈现它。我尝试了以下方法:
<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>
<object>
代码
<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>
该库发出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.
首先,我在SVG网址上添加了一个简单的<img>
标记:
return (
<img
ref={node => this.testSVG = node}
src={url} id="svg" type="image/svg+xml" />
)
这也会导致上述XMLHttpRequest
错误。尝试使用节点SVGInjector
(即componentDidMount
)或以这种方式从ref
拨打SVGInjector(this.testSVG)
:
const el = document.getElementById('svg');
SVGInjector(el);
导致警告消失但导致仅显示损坏的图像标记。
为了动画的目的,解决这些CORS
警告或关于在React中将SVG嵌入DOM的正确方法的任何帮助都将非常感激。也许我需要做的是通过服务器下载图像,并直接从服务器文件系统(例如,从/public
文件夹)暂时提供它。这不是我的首选方法,因为我已经使用AWS S3进行图像托管。
答案 0 :(得分:2)
答案是在AWS S3控制台中启用CORS。见stackoverflow.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提出此建议。正如他所提到的,如果您从另一个域中提供您无权访问的图像,则可能需要使用代理。有关详细信息,请参阅如何使用CORS代理来解决“No Access-Control-Allow-Origin标题”问题部分下的stackoverflow.com/a/43881141/441757。