使用image-webpack-loader时SVG关键帧动画失效问题求助
解决React中SVG Keyframes动画不生效的问题
我来帮你搞定这个头疼的问题!你遇到的情况其实挺常见的,主要是image-webpack-loader的优化逻辑和React里引入SVG的方式导致的,下面给你拆解原因和对应的解决方案:
为啥动画会失效?
- SVG被loader“过度优化”了:
image-webpack-loader默认会用SVGO工具压缩SVG,它可能会误把<style>里的@keyframes动画规则、甚至关联的样式属性删掉——毕竟压缩工具默认会把它认为“没用”的代码清掉,但单独打开SVG时没有经过这个压缩,所以动画正常。 - img标签的限制:用
<img>加载SVG时,浏览器会把它当成普通图片资源,SVG内部的部分样式和动画会被安全策略限制,不过结合你单独打开正常的情况,loader的压缩才是罪魁祸首。
具体解决方案
方案1:修改loader配置,保住动画代码
既然是loader把动画删了,那我们就给SVGO加规则,让它别碰动画相关的代码。修改你的webpack配置如下:
{ test: /\.(gif|png|jpe?g|svg)$/i, use: [ { loader: 'file-loader', options: { hash: 'sha512', digest: 'hex', name: '[hash].[ext]', } }, { loader: 'image-webpack-loader', options: { svgo: { plugins: [ // 禁止移除<style>标签,动画写在这里面呢 { removeStyleElement: false }, // 别删空属性,有些动画依赖的属性可能看起来是空的 { removeEmptyAttrs: false }, // 保留ID,动画里的ID关联不能丢 { cleanupIDs: false }, // 不压缩样式,防止keyframes被误删 { minifyStyles: false } ] } } } ] }
方案2:把SVG当React组件引入(更推荐!)
如果改配置还是搞不定,直接把SVG转成React组件是最靠谱的方式,动画100%能保留,还能灵活修改SVG的属性:
- 先装个处理SVG的loader:
npm install @svgr/webpack --save-dev
- 把webpack里的SVG规则和普通图片分开:
// 处理png/jpg/gif这些普通图片 { test: /\.(gif|png|jpe?g)$/i, use: [ { loader: 'file-loader', options: { hash: 'sha512', digest: 'hex', name: '[hash].[ext]', } }, { loader: 'image-webpack-loader' } ] } // 专门处理SVG,转成React组件 { test: /\.svg$/i, issuer: /\.[jt]sx?$/, // 只在js/tsx文件里用这个规则 use: ['@svgr/webpack'], }
- 在React组件里直接用:
import Logo from './你的logo文件.svg'; function App() { return ( <div className="app"> {/* 直接把SVG当组件用,动画完全正常 */} <Logo width={200} height={200} /> </div> ); }
这种方式不仅动画没问题,还能通过props直接改SVG的大小、颜色,比用img标签灵活多了。
方案3:用object标签临时救急
要是不想动webpack配置,也可以试试用<object>标签代替<img>加载SVG:
<object type="image/svg+xml" data={require('./你的logo文件.svg')} width="200" height="200" ></object>
浏览器会完整解析SVG内部的所有代码,动画就能正常跑了,不过这种方式没法像组件那样改属性,只能临时用用。
内容的提问来源于stack exchange,提问作者Arshpreet Singh Bhatti
相关产品推荐
相关产品推荐

