首页 > 解决方案 > 如何性能优化这个 SVG 动画?

问题描述

我正在制作一个 SVG 动画,这里有一个代码笔来检查它。它使用了 SVG 过滤器、SVG 蒙版和路径动画的组合。

我遇到的问题是我正在努力让它在所有设备上都能发挥作用。在具有坚固 GPU 的良好桌面上,它以合理的 FPS 运行良好。在中型笔记本电脑上,它的运行速度可能为 12 FPS,而在更基本的设备上,它的运行速度低至 2 FPS。

我尝试了很多不同的方法来提高性能,包括:

已经为此工作了很长时间,试图让这种效果在所有设备上都能以高性能的方式工作,并且非常感谢您的任何想法:)

.full-screen {
    position: fixed;
    top: 0px; left: 0px;
    width: 100%; height: 100%;
}

.svg__container {
    position: fixed;
    top: 0; left: 0;
    width: 100%; height: 100%;
}

.svg-container {
    width: 2320px;
    height: 1600px;
    position: relative;
    top: 50%; left: 50%;
    transform: translate(-38%, -49%) scale(0.4);
}

.mask__area {
    fill: white;
}

.gooey-filter {
    filter: url(#gooey-filter);
}

.drop-shadow {
    filter: url(#drop-shadow-filter);
    opacity: 0.3;
    transform: translate(30px, 30px);
}

.layer1-main {
    will-change: d;
    animation: layer1-main__animation 15s ease-in-out infinite alternate;
}

.layer1-small {
    will-change: d;
    animation: layer1-mini__animation 15s ease-in-out infinite alternate;
}

.layer2-main {
    will-change: d;
    animation: layer2-main__animation 13s ease-in-out infinite alternate;
}

.layer2-small {
    will-change: d;
    animation: layer2-mini__animation 13s ease-in-out infinite alternate;
}

.layer3 {
    will-change: d;
    animation: layer3__animation 11s ease-in-out infinite alternate;
}

.layer4 {
    will-change: d;
    animation: layer4__animation 9s ease-in-out infinite alternate;
}


@keyframes layer1-main__animation {
    0% {
        d: path("m144.81109,43.71449c27.41462,-22.10974 62.89021,-29.31703 106.8048,-28.65849c43.91459,0.65854 76.29263,18.13413 129.39015,35.84144c53.09752,17.70731 128.73155,28.86581 136.35349,95.4999c7.62194,66.63409 -4.98773,66.60971 -21.08527,114.13407c-16.09754,47.52437 -22.37806,57.25605 -49.74391,81.15847c-27.36584,23.90242 -108.36579,32.30483 -192.75592,18.56094c-84.39013,-13.74388 -155.2834,-68.88713 -167.102,-104.11269c-11.8186,-35.22556 -18.1033,-112.09064 1.46966,-148.47019c19.57297,-36.37954 29.25438,-41.84371 56.669,-63.95345z");
    }
    50% {
        d: path("m157.61597,54.6901c24.36584,-28.2073 43.98777,-36.6341 81.8048,-37.80483c37.81703,-1.17073 86.04873,21.79266 139.14625,39.49997c53.09752,17.70731 145.19496,20.93899 155.86568,87.57308c10.67072,66.63409 -58.03651,61.1219 -68.03649,101.32919c-9.99998,40.20729 -3.47562,52.98775 -22.30488,83.59749c-18.82926,30.60973 -81.53653,65.23166 -193.97544,45.99997c-112.43892,-19.23169 -178.45413,-97.54567 -180.51663,-152.89318c-2.0625,-55.34751 34.94548,-68.79795 50.25015,-101.51897c15.30467,-32.72101 13.40072,-37.57542 37.76656,-65.78272z");
    }
    100% {
        d: path("m147.25012,63.22668c13.99999,-21.49998 38.49997,-46.99995 93.99992,-49.99995c55.49995,-3 57.99995,28.49998 104.99991,39.49997c46.99996,10.99999 182.99984,18.49998 195.49983,95.49991c12.49999,76.99994 -74.49993,65.99995 -84.49991,99.49992c-9.99999,33.49997 7.49999,47.49995 -9.5,77.49993c-16.99999,29.99998 -72.99994,69.49995 -207.99983,45.99997c-134.99989,-23.49999 -176.62486,-99.37494 -178.68736,-148.62489c-2.0625,-49.24995 47.1406,-66.96868 62.44527,-96.03116c15.30467,-29.06248 9.74218,-41.84372 23.74217,-63.3437z");
    }
}

@keyframes layer1-mini__animation {
    0% {
        d: path("m152.67701,106.22571c18.49997,-3.37805 33.67071,11.99999 35.49998,34.99997c1.82927,22.99998 -17.2317,37.49997 -35.49998,36.99997c-18.26828,-0.5 -31.56096,-11.32925 -32.56095,-33.32924c-0.99999,-21.99999 14.06098,-35.29265 32.56095,-38.6707z");
    }
    50% {
        d: path("m69.75018,70.25011c18.49997,1.5 35.49998,11.99999 35.49998,34.99997c0,22.99998 -21.49999,37.49997 -35.49998,36.99997c-13.99999,-0.5 -33.99998,-9.49998 -34.99997,-31.49997c-0.99999,-21.99999 16.5,-41.99997 34.99997,-40.49997z");
    }
    100% {
        d: path("m69.75018,70.25011c18.49997,1.5 35.49998,11.99999 35.49998,34.99997c0,22.99998 -21.49999,37.49997 -35.49998,36.99997c-13.99999,-0.5 -33.99998,-9.49998 -34.99997,-31.49997c-0.99999,-21.99999 16.5,-41.99997 34.99997,-40.49997z");
    }
}


@keyframes layer2-main__animation {
    0% {
        d: path("m439.55475,141.46957c-11.23169,-22.36582 -44.85361,-46.91461 -79.14627,-66.03654c-34.29267,-19.12193 -74.0975,-35.74387 -118.09746,-26.74388c-43.99996,8.99999 -112.91455,86.35358 -82.91456,181.3535c29.99998,94.99993 129.35354,115.51211 178.3535,108.01211c48.99996,-7.5 77.6219,-49.30484 92.62187,-84.3048c14.99998,-34.99997 20.41461,-89.91456 9.18292,-112.28039z");
    }
    50% {
        d: path("m451.74987,140.25006c-15.49998,-36.99997 -53.99995,-33.49998 -94.99993,-57.49996c-40.99998,-23.99997 -67.99994,-45.49996 -111.9999,-36.49997c-43.99996,8.99999 -124.49991,95.49992 -94.49992,190.49984c29.99998,94.99993 138.49988,120.99991 187.49984,113.49991c48.99996,-7.5 82.49995,-61.49996 97.49992,-96.49992c14.99998,-34.99997 31.99997,-76.49993 16.49999,-113.4999z");
    }
    100% {
        d: path("m340.24996,175.25003c-6.99999,-37.99997 2,-67.49995 -14.49999,-102.99992c-16.49999,-35.49997 -63.49995,-36.99997 -96.99992,-25.99998c-33.49997,10.99999 -116.4999,79.99994 -72.49994,191.99984c43.99997,111.99991 148.49988,127.99989 197.49984,110.49991c48.99996,-17.49999 64.99995,-61.99995 57.49995,-87.99993c-7.49999,-25.99998 -53.49996,-29.49997 -70.99994,-85.49992z");
    }
}

@keyframes layer2-mini__animation {
    0% {
        d: path("m301.74998,142.25005c-29.49997,0 -56.49995,21.49998 -57.99995,55.99995c-1.5,34.49997 25.49998,61.49995 58.99995,62.99995c33.49997,1.5 58.49995,-28.99998 58.49995,-60.99995c0,-31.99997 -29.99997,-57.99995 -59.49995,-57.99995z");
    }
    50% {
        d: path("m301.74998,142.25005c-29.49997,0 -56.49995,21.49998 -57.99995,55.99995c-1.5,34.49997 25.49998,61.49995 58.99995,62.99995c33.49997,1.5 58.49995,-28.99998 58.49995,-60.99995c0,-31.99997 -29.99997,-57.99995 -59.49995,-57.99995z");
    }
    100% {
        d: path("m416.74989,98.25009c-29.49997,0 -56.49995,21.49998 -57.99995,55.99995c-1.5,34.49997 25.49998,61.49995 58.99995,62.99995c33.49997,1.5 58.49995,-28.99998 58.49995,-60.99995c0,-31.99997 -29.99997,-57.99995 -59.49995,-57.99995z");
    }
}

@keyframes layer3__animation {
    0% {
        d: path("m190.5062,251.21337c-18.52436,-42.76824 -10.2317,-93.84136 3.41461,-118.71939c13.64632,-24.87803 42.98778,-32.51219 69.98775,-39.51218c26.99998,-6.99999 41.79266,-13.15853 65.1219,-10.59755c23.32924,2.56098 25.98778,8.03656 45.48776,19.03656c19.49998,11 46.80484,28.48783 49.17068,43.21948c2.36583,14.73165 2.78049,17.81703 -0.57316,42.78043c-3.35365,24.96341 -15.35366,43.19511 -30.19509,63.63413c-14.84143,20.43902 -22.14632,46.79262 -73.45115,62.89017c-51.30484,16.09755 -110.43894,-19.96341 -128.9633,-62.73165z");
    }
    50% {
        d: path("m184.40864,257.31093c-29.49998,-63.49995 -7.79268,-130.42673 12.56095,-146.15842c20.35363,-15.73169 39.939,-6.90243 66.93897,-13.90242c26.99998,-6.99999 39.96338,-19.86583 65.1219,-19.13413c25.15851,0.73171 25.98778,12.30485 45.48776,23.30485c19.49998,11 54.73167,26.65856 65.63409,49.9268c10.90242,23.26824 13.7561,42.20727 -0.57316,56.80482c-14.32926,14.59755 -22.06097,11.48779 -40.56094,33.75608c-18.49997,22.26828 -31.90242,64.47555 -83.20725,80.5731c-51.30484,16.09755 -101.90235,-1.67073 -131.40232,-65.17068z");
    }
    100% {
        d: path("m180.7501,259.74995c-29.49998,-63.49995 -14.5,-122.49989 14.99998,-142.49988c29.49997,-19.99998 37.49997,-12.99999 64.49994,-19.99998c26.99998,-6.99999 48.49997,-34.49998 69.99995,-29.49998c21.49998,5 20.49998,24.49997 39.99996,35.49997c19.49998,11 58.99996,-1.99998 75.99994,41.99997c16.99999,43.99996 4,60.49995 -8.49999,68.99994c-12.49999,8.49999 -24.49999,5.99999 -42.99996,23.99998c-18.49998,17.99999 -37.99998,78.49994 -76.49994,88.49993c-38.49997,9.99999 -107.99991,-3.5 -137.49988,-66.99995z");
    }
}

@keyframes layer4__animation {
    0% {
        d: path("m229.44518,257.49385c-17.51218,-26.35363 -17.14633,-82.87797 19.79266,-110.97551c36.939,-28.09754 66.69506,-28.12192 99.19503,-19.12193c32.49998,8.99999 47.39018,37.68288 47.26824,60.97555c-0.12194,23.29266 -6.40241,41.64631 -27.90239,58.6463c-21.49998,16.99998 -40.30486,31.29265 -60.97557,37.19508c-20.67071,5.90243 -59.8658,-0.36586 -77.37797,-26.71949z");
    }
    50% {
        d: path("m218.46957,265.42068c-22.99998,-35.49997 -6.17072,-90.8048 30.76827,-118.90234c36.939,-28.09754 71.57311,-26.29265 104.07308,-17.29266c32.49998,8.99999 57.75603,36.46337 57.63409,59.75604c-0.12194,23.29266 -21.64631,41.03655 -43.14629,58.03654c-21.49998,16.99998 -37.25608,31.90241 -59.75606,43.9024c-22.49998,11.99999 -66.57311,9.99999 -89.57309,-25.49998z");
    }
    100% {
        d: path("m217.25006,267.24995c-22.99998,-35.49997 -7.99999,-102.99992 26.49998,-124.9999c34.49997,-21.99998 79.49993,-32.99997 111.9999,-23.99998c32.49998,8.99999 72.99994,44.99996 67.99995,74.99994c-5,29.99997 -37.49997,32.49997 -58.99995,49.49996c-21.49998,16.99998 -27.49998,37.99997 -49.99996,49.99996c-22.49998,11.99999 -74.49994,9.99999 -97.49992,-25.49998z");
    }
}
<div class="full-screen background"></div>
<div class="svg__container">
    <svg class="svg-container">
        
        <defs>
            <filter id="gooey-filter">
                <feGaussianBlur in="SourceGraphic" stdDeviation="20" result="blur" />
                <feColorMatrix in="blur" type="matrix" values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 19 -9" result="goo" />
                <feComposite in="SourceGraphic" in2="goo" operator="atop" />
            </filter>

            <filter id="drop-shadow-filter">
                <feGaussianBlur in="SourceGraphic" stdDeviation="30" result="blur" />
            </filter>
        </defs>


        <rect class="full-screen" fill="#003459"></rect>


        <mask id="mask4">
            <rect class="mask__area" width="100%" height="100%" />
            <path class="layer4" transform="scale(4)" fill="black" d="m229.44518,257.49385c-17.51218,-26.35363 -17.14633,-82.87797 19.79266,-110.97551c36.939,-28.09754 66.69506,-28.12192 99.19503,-19.12193c32.49998,8.99999 47.39018,37.68288 47.26824,60.97555c-0.12194,23.29266 -6.40241,41.64631 -27.90239,58.6463c-21.49998,16.99998 -40.30486,31.29265 -60.97557,37.19508c-20.67071,5.90243 -59.8658,-0.36586 -77.37797,-26.71949z" />
        </mask>
        
        <g class="drop-shadow">
            <g class="full-screen gooey-filter">
                <rect fill="black" width="100%" height="100%" mask="url(#mask4)"></rect>
            </g>
        </g>

        <g class="full-screen gooey-filter">
            <rect fill="rgb(0, 96, 132)" style="transform: translate(18px, 18px);" width="100%" height="100%" mask=url(#mask4)></rect>
            <rect fill="rgb(0, 101, 142)" style="transform: translate(15px, 15px);" width="100%" height="100%" mask=url(#mask4)></rect>
            <rect fill="rgb(0, 106, 147)" style="transform: translate(12px, 12px);" width="100%" height="100%" mask=url(#mask4)></rect>
            <rect fill="rgb(0, 111, 152)" style="transform: translate(9px, 9px);" width="100%" height="100%" mask=url(#mask4)></rect>
            <rect fill="rgb(0, 116, 157)" style="transform: translate(6px, 6px);" width="100%" height="100%" mask=url(#mask4)></rect>
            <rect fill="rgb(0, 121, 162)" style="transform: translate(3px, 3px);" width="100%" height="100%" mask=url(#mask4)></rect>
            <rect fill="#007EA7" width="100%" height="100%" mask=url(#mask4)></rect>
        </g>


        <mask id="mask3">
            <rect class="mask__area" width="100%" height="100%" />
            <path class="layer3" transform="scale(4)" fill="black" d="m190.5062,251.21337c-18.52436,-42.76824 -10.2317,-93.84136 3.41461,-118.71939c13.64632,-24.87803 42.98778,-32.51219 69.98775,-39.51218c26.99998,-6.99999 41.79266,-13.15853 65.1219,-10.59755c23.32924,2.56098 25.98778,8.03656 45.48776,19.03656c19.49998,11 46.80484,28.48783 49.17068,43.21948c2.36583,14.73165 2.78049,17.81703 -0.57316,42.78043c-3.35365,24.96341 -15.35366,43.19511 -30.19509,63.63413c-14.84143,20.43902 -22.14632,46.79262 -73.45115,62.89017c-51.30484,16.09755 -110.43894,-19.96341 -128.9633,-62.73165z" />
        </mask>
        
        <g class="drop-shadow">
            <g class="full-screen gooey-filter">
                <rect fill="black" width="100%" height="100%" mask="url(#mask3)"></rect>
            </g>
        </g>

        <g class="full-screen gooey-filter">
            <rect fill="rgb(0,138,202)" style="transform: translate(18px, 18px);" width="100%" height="100%" mask=url(#mask3)></rect>
            <rect fill="rgb(0,143,207)" style="transform: translate(15px, 15px);" width="100%" height="100%" mask=url(#mask3)></rect>
            <rect fill="rgb(0,148,212)" style="transform: translate(12px, 12px);" width="100%" height="100%" mask=url(#mask3)></rect>
            <rect fill="rgb(0,153,217)" style="transform: translate(9px, 9px);" width="100%" height="100%" mask=url(#mask3)></rect>
            <rect fill="rgb(0,158,222)" style="transform: translate(6px, 6px);" width="100%" height="100%" mask=url(#mask3)></rect>
            <rect fill="rgb(0,163,227)" style="transform: translate(3px, 3px);" width="100%" height="100%" mask=url(#mask3)></rect>
            <rect fill="#00A8E8" width="100%" height="100%" mask=url(#mask3)></rect>
        </g>


        <mask id="mask2">
            <rect class="mask__area" width="100%" height="100%" />
            <path class="layer2-main" transform="scale(4)" fill="black" d="m439.55475,141.46957c-11.23169,-22.36582 -44.85361,-46.91461 -79.14627,-66.03654c-34.29267,-19.12193 -74.0975,-35.74387 -118.09746,-26.74388c-43.99996,8.99999 -112.91455,86.35358 -82.91456,181.3535c29.99998,94.99993 129.35354,115.51211 178.3535,108.01211c48.99996,-7.5 77.6219,-49.30484 92.62187,-84.3048c14.99998,-34.99997 20.41461,-89.91456 9.18292,-112.28039z" />
            <path class="layer2-small" transform="scale(4)" fill="black" d="m301.74998,142.25005c-29.49997,0 -56.49995,21.49998 -57.99995,55.99995c-1.5,34.49997 25.49998,61.49995 58.99995,62.99995c33.49997,1.5 58.49995,-28.99998 58.49995,-60.99995c0,-31.99997 -29.99997,-57.99995 -59.49995,-57.99995z" />
        </mask>

        <g class="drop-shadow">
            <g class="full-screen gooey-filter">
                <rect fill="black" width="100%" height="100%" mask="url(#mask2)"></rect>
            </g>
        </g>
        
        <g class="full-screen gooey-filter">
            <rect fill="rgb(217,217,219)" style="transform: translate(18px, 18px);" width="100%" height="100%" mask=url(#mask2)></rect>
            <rect fill="rgb(222,222,224)" style="transform: translate(15px, 15px);" width="100%" height="100%" mask=url(#mask2)></rect>
            <rect fill="rgb(227,227,229)" style="transform: translate(12px, 12px);" width="100%" height="100%" mask=url(#mask2)></rect>
            <rect fill="rgb(232,232,234)" style="transform: translate(9px, 9px);" width="100%" height="100%" mask=url(#mask2)></rect>
            <rect fill="rgb(237,237,239)" style="transform: translate(6px, 6px);" width="100%" height="100%" mask=url(#mask2)></rect>
            <rect fill="rgb(242,242,244)" style="transform: translate(3px, 3px);" width="100%" height="100%" mask=url(#mask2)></rect>
            <rect fill="#F7F7F9" width="100%" height="100%" mask=url(#mask2)></rect>
        </g>
        


        <mask id="mask1">
            <rect class="mask__area" width="100%" height="100%" />
            <path class="layer1-main" transform="scale(4)" fill="black" d="m144.81109,43.71449c27.41462,-22.10974 62.89021,-29.31703 106.8048,-28.65849c43.91459,0.65854 76.29263,18.13413 129.39015,35.84144c53.09752,17.70731 128.73155,28.86581 136.35349,95.4999c7.62194,66.63409 -4.98773,66.60971 -21.08527,114.13407c-16.09754,47.52437 -22.37806,57.25605 -49.74391,81.15847c-27.36584,23.90242 -108.36579,32.30483 -192.75592,18.56094c-84.39013,-13.74388 -155.2834,-68.88713 -167.102,-104.11269c-11.8186,-35.22556 -18.1033,-112.09064 1.46966,-148.47019c19.57297,-36.37954 29.25438,-41.84371 56.669,-63.95345z" />
            <path class="layer1-small" transform="scale(4)" fill="black" d="m152.67701,106.22571c18.49997,-3.37805 33.67071,11.99999 35.49998,34.99997c1.82927,22.99998 -17.2317,37.49997 -35.49998,36.99997c-18.26828,-0.5 -31.56096,-11.32925 -32.56095,-33.32924c-0.99999,-21.99999 14.06098,-35.29265 32.56095,-38.6707z" />
        </mask>

        <g class="drop-shadow">
            <g class="full-screen gooey-filter">
                <rect fill="black" width="100%" height="100%" mask="url(#mask1)"></rect>
            </g>
        </g>
        
        <g class="full-screen gooey-filter">
            <rect fill="rgb(225,225,225)" style="transform: translate(18px,18px);" width="100%" height="100%" mask=url(#mask1)></rect>
            <rect fill="rgb(230,230,230)" style="transform: translate(15px,15px);" width="100%" height="100%" mask=url(#mask1)></rect>
            <rect fill="rgb(235,235,235)" style="transform: translate(12px,12px);" width="100%" height="100%" mask=url(#mask1)></rect>
            <rect fill="rgb(240,240,240)" style="transform: translate(9px,9px);" width="100%" height="100%" mask=url(#mask1)></rect>
            <rect fill="rgb(245,245,245)" style="transform: translate(6px,6px);" width="100%" height="100%" mask=url(#mask1)></rect>
            <rect fill="rgb(250,250,250)" style="transform: translate(3px,3px);" width="100%" height="100%" mask=url(#mask1)></rect>
            <rect fill="white" width="100%" height="100%" mask=url(#mask1)></rect>
        </g>


        <!-- Border -->
        <rect stroke="white" stroke-width="20px" width="100%" height="100%" fill="rgba(0,0,0,0)"></rect>

    </svg>
</div>  

标签: htmlcsssvgsvg-filterssvg-animate

解决方案


推荐阅读