CSS动画冻结

Posted

技术标签:

【中文标题】CSS动画冻结【英文标题】:CSS animation freezing 【发布时间】:2020-01-27 11:28:46 【问题描述】:

等待我的 Angular 应用程序通过 ajax 加载所需的所有内容,我在内容上方的较暗层上显示了一个加载器。

我正在使用这个包含 animateTransform 的 SVG:

<svg   viewBox="0 0 38 38" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient x1="8.042%" y1="0%" x2="65.682%" y2="23.865%" id="a"><stop stop-color="#fff" stop-opacity="0" offset="0%"/><stop stop-color="#fff" stop-opacity=".631" offset="63.146%"/><stop stop-color="#fff" offset="100%"/></linearGradient></defs><g fill="none" fill-rule="evenodd"><g transform="translate(1 1)"><path d="M36 18c0-9.94-8.06-18-18-18" stroke="url(#a)" stroke-><animateTransform attributeName="transform" type="rotate" from="0 18 18" to="360 18 18" dur="0.9s" repeatCount="indefinite" /></path><circle fill="#fff" cx="36" cy="18" r="1"><animateTransform attributeName="transform" type="rotate" from="0 18 18" to="360 18 18" dur="0.9s" repeatCount="indefinite" /></circle></g></g></svg>

ajax 调用次数为 4 次,加载程序在某个时间点冻结​​,调用完成后动画再次开始。

这是角部分:

<script type="text/javascript">
var myApp = angular
    .module('appName', [], function($interpolateProvider) 
        $interpolateProvider.startSymbol('<%');
        $interpolateProvider.endSymbol('%>');
    
    .service('dataService', function($http) 
        function getInfos() 
            return $http.get(currentUrl + '/infos');
        
        function getCountries() 
            return $http.get(currentUrl + '/countries');
        
        function getCatgeories() 
            return $http.get(currentUrl + '/categories');
        
        function getPrices() 
            return $http.get(currentUrl + '/prices');
        
        return 
            getInfos: getInfos,
            getCountries: getCountries,
            getCatgeories: getCatgeories,
            getPrices: getPrices
        ;
    )
    .controller('appNameController', function($scope, dataService) 
        $scope._loading = 
            start: function() 
                if($('.loader').hasClass('off'))
                    $('.loader').removeClass('off');
                
            ,
            stop: function() 
                if(!$('.loader').hasClass('off'))
                    $('.loader').addClass('off');
                
            
        ;
        $scope._loading.start();
        $scope.checkPageLoader = function() 
            if($scope.hidePageLoader == 4) 
                    $('#loaderText').html('<span>App is Ready!</span>');
                    $scope._loading.stop();
            
        ;
        $scope.hidePageLoader = 0;
        $scope.getInfos = function() 
            dataService.getInfos().then(function(res) 
                $scope.infos = res.data;
                $scope.hidePageLoader += 1;
                $('#loaderText').append('<span><i class="icon-check"></i>Infos</span>');
                $scope.checkPageLoader();
            );
        ;
        dataService.getCatgeories().then(function(res) 
            $scope.categories = res.data;
            $scope.hidePageLoader += 1;
            $('#loaderText').append('<span><i class="icon-check"></i>Categories</span>');
            $scope.checkPageLoader();
        );
        dataService.getPrices().then(function(res) 
            $scope.prices = res.data;
            $scope.hidePageLoader += 1;
            $('#loaderText').append('<span><i class="icon-check"></i>Prices</span>');
            $scope.checkPageLoader();
        );
        $scope.getCountries = function() 
            dataService.getCountries().then(function(res) 
                $scope.countries = res.data;
                $scope.hidePageLoader += 1;
                $('#loaderText').append('<span><i class="icon-check"></i>Countries</span>');
                $scope.checkPageLoader();
            );
        ;
        angular.element(document).ready(function () 
            $scope._loading.start();
            $scope.getInfos();
            $scope.getCountries();
            /* $scope.priceValues(); */
        );
    );
</script>

知道为什么会这样吗?

【问题讨论】:

这很常见,他们都在使用主线程。您可以尝试使用 css 转换来查看更简单的非 svg 加载器是否可以工作,或者将您的请求从主线程移到工作线程,但我认为这太过分了。或者,如果它有点紧张,就忍受它。 我在 SO 上读到了类似的内容,关于使用另一个线程,但我不知道如何实现它.. 【参考方案1】:

我最终从 SVG 的嵌入式动画转移到 CSS 动画,始终在 SVG 上。

现在的 SVG 代码是:

<svg   viewBox="0 0 38 38" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient x1="8.042%" y1="0%" x2="65.682%" y2="23.865%" id="a"><stop stop-color="#fff" stop-opacity="0" offset="0%"/><stop stop-color="#fff" stop-opacity=".631" offset="63.146%"/><stop stop-color="#fff" offset="100%"/></linearGradient></defs><g fill="none" fill-rule="evenodd"><g transform="translate(1 1)"><path d="M36 18c0-9.94-8.06-18-18-18" stroke="url(#a)" stroke-></path><circle fill="#fff" cx="36" cy="18" r="1"></circle></g></g></svg>

这是复制嵌入动画的 CSS 代码 (animateTransform):

#pageLoader 
    animation: spin 1s infinite linear;


@keyframes spin 
  0% 
    transform: rotate(0deg);
  
  100% 
    transform: rotate(359deg);
  

这样动画很流畅,在 ajax 调用期间不会冻结。

希望这会对某人有所帮助。

【讨论】:

【参考方案2】:

您的代码不正确:priceValues 不存在

尝试使用$q.all 等待所有承诺:

.controller('appNameController', function($scope, $q, dataService) 
    $scope._loading = 
        start: function() 
            if($('.loader').hasClass('off'))
                $('.loader').removeClass('off');
            
        ,
        stop: function() 
            if(!$('.loader').hasClass('off'))
                $('.loader').addClass('off');
            
        
    ;
    $scope.getInfos = function() 
        return dataService.getInfos().then(function(res) 
            $scope.infos = res.data;
        );
    ;
    $scope.getCatgeories= function() 
        return dataService.getCatgeories().then(function(res) 
            $scope.categories = res.data;
        );
    ;
    $scope.getPrices= function() 
        return dataService.getPrices().then(function(res) 
            $scope.prices = res.data;
        );
    ;
    $scope.getCountries = function() 
        return dataService.getCountries().then(function(res) 
            $scope.countries = res.data;
        );
    ;
    $scope._loading.start();
    $q.all([
        $scope.getInfos(),
        $scope.getPrices(),
        $scope.getCountries()
    ]).then(function() 
        $('#loaderText').html('<span>App is Ready!</span>');
        $scope._loading.stop();
    );
);

【讨论】:

问题不在于角度,我在控制台中没有错误,并且所有日期都很好。只是 CSS 动画同时冻结...加上 $scope.priceValues();不用了,我注释掉了

以上是关于CSS动画冻结的主要内容,如果未能解决你的问题,请参考以下文章

为啥 JavaScript 会阻止 CSS 动画和过渡?

css3动画效果,如何设置呢?

怎么用js触发css3动画

如何触发css3过渡动画

css3动画使用

点击播放 css3 动画