【问题标题】:SVG progress circle image rotation orientationSVG进度圈图像旋转方向
【发布时间】:2021-02-19 10:14:21
【问题描述】:

我正在尝试创建一个圆形进度条(如下图所示)。进度以百分比为基础,并将绕圈移动到该百分比。 我的进度正在移动,但随之移动的图标需要具有正确的方向。正如下面的图像,当它应该面向屏幕底部时,图像底部面向中心。图像需要与栏一起移动。

<div class="case_progress_wrapper" data-percent="80">
 <svg class="case_progress_circle" height="100%" width="100%" viewBox="0 0 140 140">
  <circle id="case_progress__path" cx="70" cy="70" r="54" fill="none" stroke="#EBEDF8" stroke-width="1" />
  <circle class="case_progress__value" cx="70" cy="70" r="54" fill="none" stroke="#f00" stroke-width="6" />
  <circle class="case_progress__inner" cx="70" cy="70" r="44" fill="#fff" stroke="#fff" stroke-width="1" />
  <circle class="case_progress__start" cx="124" cy="63" r="3" fill="#fff" stroke="#fff" stroke-width="1" />
  <g id='case_progress__prog_fill' class="case_progress__prog" viewBox="0 0 60 60">
    <circle fill="url(#image)" cx="124" cy="63" r="8" stroke="#fff" stroke-width="1" />
  </g>
  <defs>
    <pattern id="image" x="0%" y="0%" height="100%" width="100%" viewBox="0 0 60 60">
      <image x="0%" y="0%" width="60" height="60" xlink:href="https://via.placeholder.com/150x150"></image>
    </pattern>
  </defs>
 </svg>
</div>
   

   
(function(){
            var $wrapper = $('.case_progress_wrapper'),
                $progress = $('.case_progress__value'),
                $circle_path = $('#case_progress__path'),
                $complete_circle = $('.case_progress__prog'),
                $percent = $wrapper.data('percent');

            setTimeout(function () {
                $progress.css('transition', 'all 2s');
                $progress.css('stroke-dashoffset', 'calc(339.292 - (' + $percent + ' * 339.292 / 100))');
                $complete_circle.css('transition', 'all 2s');
                $complete_circle.attr("transform", 'rotate(' + (360 - ($percent - 25)) + ',' + $circle_path.attr('cx') + ',' + $circle_path.attr('cy') +')');

                setTimeout(function () {
                    $progress.css('transition', 'none');
                    $complete_circle.css('transition', 'all 2s');
                }, 2000);

            }, 1000);

        })();

【问题讨论】:

    标签: javascript html jquery svg


    【解决方案1】:

    纯 SVG 解决方案和一些用于百分比输出的 JS

    就像这个question

    要解决,需要结合两个动画:

    1. 从头到尾绘制圆弧
    2. 内部带有图像的圆圈运动动画

    为两个动画设置相同的时间

    请阅读代码中的cmets。

    var count = $(('#count'));
    $({ Counter: 0 }).animate({ Counter: count.text() }, {
      duration: 10000,
      easing: 'linear',
      step: function () {
        count.text(Math.ceil(this.Counter)+ "%");
      }
    });
    </script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div class="case_progress_wrapper" data-percent="80" style="width:50vw; height:50vh;">
     <svg class="case_progress_circle"  viewBox="0 0 140 140">
    <defs>
        <pattern id="image" x="0%" y="0%" height="100%" width="100%" viewBox="1 0 58 58">
          <image  x="0%" y="0%" width="60" height="60" xlink:href="https://i.stack.imgur.com/uQMJ3.jpg"></image>
        </pattern>
      </defs>
     <rect width="100%" height="100%" fill="#87CEEB" />
     <g transform="rotate(-90 70 70)" >  
        <!-- Track for rotating a circle with an image -->
     <path id="case_progress__path"       
         style="fill:none;stroke:#ebedf8;stroke-width:1"
         d="M 124,70 A 54,54 0 0 1 70,124 54,54 0 0 1 16,70 54,54 0 0 1 70,16 54,54 0 0 1 124,70 Z"/>
      
       <!-- Circle for the growth of the red progress bar -->
     <circle  
      class="case_progress__value" stroke-dashoffset="339.5" stroke-dasharray="339.5" cx="70" cy="70" r="54" fill="none" stroke="#f00" stroke-width="6" >
         <!-- Bar progress animation -->
       <animate attributeName="stroke-dashoffset" begin="0s" dur="10s" values="339.5;0" fill="freeze" /> 
        </circle> 
     <!-- Starting point -->
    <circle class="case_progress__start" cx="124" cy="70" r="3" fill="#fff" stroke="#fff" stroke-width="1" />
      <g id='case_progress__prog_fill' class="case_progress__prog" viewBox="1 0 58 58">
      <circle transform="rotate(90 0 0)" fill="url(#image)" cx="0" cy="0"  r="8" stroke-width="0.25" stroke="#fff"   > 
          <!-- Icon rotation animation -->
            <animateMotion begin="0s" dur="10s" fill="freeze"   >
          <mpath xlink:href="#case_progress__path" /> 
          </animateMotion> 
      </circle>
      </g>  
        </g>
    
     <circle class="case_progress__inner" cx="70" cy="70" r="44" fill="#fff" stroke="#fff" stroke-width="1" />
      <text id="count" x="50%" y="50%" fill="red" text-anchor="middle" dy="7" font-size="20">100%</text>
     </svg>
    </div> 

    【讨论】:

    • 这非常有效,帮助我实现了我需要的东西。我必须编辑代码,所以这不是一个简单的复制和粘贴工作,但这让我对 SVG 有了更多的了解,也帮助了我为该项目所做的其他设计。我将上传我的新代码作为编辑。谢谢!
    • @Bryan88 很高兴能为您提供帮助。感谢您的积极反馈,并祝您成功掌握 SVG。
    【解决方案2】:

    您需要做的就是将&lt;circle&gt; 与图标/图像沿相反方向旋转相同的量。

        $complete_circle_circ = $('.case_progress__prog circle'),
    
        ...
    
        $complete_circle_circ.css({'transition': 'transform 2s',
                                   'transform-box': 'fill-box',
                                   'transform-origin': '50% 50%'});
        $complete_circle_circ.attr("transform", 'rotate(' + (-$rotation) + ')');
    

    顺便说一句,我还修正了你的百分比->轮换计算。

    $rotation = $percent * 360 / 100;
    

    (function(){
        var $wrapper = $('.case_progress_wrapper'),
            $progress = $('.case_progress__value'),
            $circle_path = $('#case_progress__path'),
            $complete_circle = $('.case_progress__prog'),
            $complete_circle_circ = $('.case_progress__prog circle'),
            $percent = $wrapper.data('percent'),
            $rotation = $percent * 360 / 100;
    
        setTimeout(function () {
            $progress.css('transition', 'all 2s');
            $progress.css('stroke-dashoffset', 'calc(339.292 - (' + $percent + ' * 339.292 / 100))');
            $complete_circle.css('transition', 'all 2s');
            $complete_circle.attr("transform", 'rotate(' + $rotation + ',' + $circle_path.attr('cx') + ',' + $circle_path.attr('cy') +')');
            $complete_circle_circ.css({'transition': 'transform 2s', 'transform-box': 'fill-box', 'transform-origin': '50% 50%'});
            $complete_circle_circ.attr("transform", 'rotate(' + (-$rotation) + ')');
    
            setTimeout(function () {
                $progress.css('transition', 'none');
                $complete_circle.css('transition', 'all 2s');
            }, 2000);
    
        }, 1000);
    
    })();
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    ```
    <div class="case_progress_wrapper" data-percent="80">
     <svg class="case_progress_circle" height="100%" width="100%" viewBox="0 0 140 140">
      <circle id="case_progress__path" cx="70" cy="70" r="54" fill="none" stroke="#EBEDF8" stroke-width="1" />
      <circle class="case_progress__value" cx="70" cy="70" r="54" fill="none" stroke="#f00" stroke-width="6" />
      <circle class="case_progress__inner" cx="70" cy="70" r="44" fill="#fff" stroke="#fff" stroke-width="1" />
      <circle class="case_progress__start" cx="124" cy="63" r="3" fill="#fff" stroke="#fff" stroke-width="1" />
      <g id='case_progress__prog_fill' class="case_progress__prog">
        <circle fill="url(#image)" cx="124" cy="63" r="8" stroke="#fff" stroke-width="1" />
      </g>
      <defs>
        <pattern id="image" x="0%" y="0%" height="100%" width="100%" viewBox="0 0 60 60">
          <image x="0%" y="0%" width="60" height="60" xlink:href="https://via.placeholder.com/150x150"></image>
        </pattern>
      </defs>
     </svg>
    </div>
    ```
    
    ```

    【讨论】:

      猜你喜欢
      • 2011-10-13
      • 2014-04-25
      • 2011-07-10
      • 2019-09-14
      • 2020-10-02
      • 2018-07-01
      • 1970-01-01
      • 2016-09-13
      • 2023-03-25
      相关资源
      最近更新 更多