一个基于svg的圆形loading动画

本文介绍了一个基于SVG的加载动画控件的实现方法,包括HTML、CSS、JavaScript的使用,以及如何通过调整参数实现不同状态下的动画效果。兼容性方面,强调现代浏览器的良好支持,同时指出对于较旧浏览器的支持有限。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

很多时候大家都要做一些loading动画,现在给大家带来的是用svg画出来的loading动画,稍微封装就可以使用了。

代码

<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2015/9/16
  Time: 16:01
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>一个基于svg的loading控件。</title>
  <script type="text/javascript" src="/static/lib/jquery-1.11.0.min.js"></script>
  <script type="text/javascript" src="/static/vendor/laytpl/laytpl.js"></script>
</head>
<body>
<h2>原型。</h2>
<svg width="200" height="200">
  <ellipse rx="90" ry="90" cx="100" cy="100" stroke="#f2f2f2" fill="none" stroke-width="10"></ellipse>
  <path fill="none" stroke="#3daf2c" stroke-width="10" d="M100,10 A90,90 0 1 1 10,90"></path>
</svg>
<h3>控件模样。</h3>
<div id="container">

</div>
<script type="text/javascript">
  function SVGLoading(_opts){
    var settings={
      strokeWidth:10 //边框宽度。
      ,strokeNormalColor:"#f2f2f2" //普通状态下边框颜色。
      ,strokeActivityColor:"#3daf2c" //激活状态下边框颜色。
      ,radius:80 //该圆形loading框的半径。
      ,percent:47 //当前默认显示的百分比。
      ,container:""
    };

    var appData={
      width:0
      ,height:0
      ,rx:0
      ,ry:0
      ,cx:0
      ,cy:0
      ,stroke1:""
      ,stroke2:""
      ,strokeWidth:0
      ,d:""
    };
    var _d_data={
      move_point:{x:0,y:0}
      ,radiusPoint:{x:0,y:0}
    };


    var _tpl_html='<svg width="{{d.width}}" height="{{d.height}}"><ellipse rx="{{d.rx}}" ry="{{d.ry}}" cx="{{d.cx}}" cy="{{d.cy}}" stroke="{{d.stroke1}}" fill="none" stroke-width="{{d.strokeWidth}}"></ellipse><path ui="path" fill="none" stroke="{{d.stroke2}}" stroke-width="{{d.strokeWidth}}" d="{{d.d}}"></path></svg>';

    var tpl=laytpl(_tpl_html);
    var _root="";
    var _el_path="";
    var app={
      init:function(){
        $.extend(settings,_opts);
        var _me=this;
        _me.initData();
        _me.initView();
      }
      //--计算原始的尺寸及其他信息。
      ,initData:function(){
        var me=this;
        appData.width=settings.radius*2;
        appData.height=settings.radius*2;
        appData.strokeWidth=settings.strokeWidth;
        appData.rx=parseInt((settings.radius-settings.strokeWidth));
        appData.ry=appData.rx;
        appData.cx=parseInt(settings.radius);
        appData.cy=appData.cx;
        appData.stroke1=settings.strokeNormalColor;
        appData.stroke2=settings.strokeActivityColor;
        _d_data.move_point={
          x:appData.cx
          ,y:appData.cy-appData.ry
        };
        _d_data.radiusPoint={
          x:appData.cx
          ,y:appData.cy
        };
      }
      ,initView:function(){
        var me=this;
        _root=$(settings.container);
        appData.d=me.caculateD(settings.percent);
        var html1=tpl.render(appData);
        _root.html(html1);
        _el_path=_root.find('[ui="path"]')[0];
      }
      //--计算 路径的d。
      ,caculateD:function(percent){

        var me=this;
        var _is_big_arc=false;
        var _realpercent=percent;
        if(_realpercent<0){
          _realpercent=0;
        }
        else if(_realpercent>100){
          _realpercent=100;
        }
        if(_realpercent>50){
          _is_big_arc=true;
        }
        var _endPoint=me.caculatePointByPercent(percent);

        var _bigArc=0;
        if(_is_big_arc){
          _bigArc=1;
        }

        var _str="M"+_d_data.move_point.x+","+_d_data.move_point.y+" A"+appData.rx+","+appData.rx+" 0 "+_bigArc+" 1 "+_endPoint.x+","+_endPoint.y+"";

        return _str;


      }
      //--计算 路径的d。
      ,caculateDbyAngle:function(angle){

        var me=this;
        var _is_big_arc=false;
        var _angle=360+angle;
        _angle=_angle%360;

        if(_angle>180){
          _is_big_arc=true;
        }
        var _endPoint=me.caculatePointByAngle(_angle);

        var _bigArc=0;
        if(_is_big_arc){
          _bigArc=1;
        }

        var _str="M"+_d_data.move_point.x+","+_d_data.move_point.y+" A"+appData.rx+","+appData.rx+" 0 "+_bigArc+" 1 "+_endPoint.x+","+_endPoint.y+"";

        return _str;


      }
      //--计算当前percent的终点。
      ,caculatePointByPercent:function(percent){
        var _res={x:0,y:0};
        /**
         圆点坐标:(x0,y0)
         半径:r
         角度:a0

         则圆上任一点为:(x1,y1)
         x1   =   x0   +   r   *   cos(ao   *   3.14   /180   )
         y1   =   y0   +   r   *   sin(ao   *   3.14   /180   )
         * */


         var Angle0=(percent/100)*360;
        Angle0=(360+Angle0-90)%360;
        _res.x= _d_data.radiusPoint.x+appData.rx*Math.cos(Angle0*Math.PI/180);
        _res.y= _d_data.radiusPoint.y+appData.rx*Math.sin(Angle0*Math.PI/180);

        return _res;
      }
      ,caculatePointByAngle:function(angle){
        var _res={x:0,y:0};
        /**
         圆点坐标:(x0,y0)
         半径:r
         角度:a0

         则圆上任一点为:(x1,y1)
         x1   =   x0   +   r   *   cos(ao   *   3.14   /180   )
         y1   =   y0   +   r   *   sin(ao   *   3.14   /180   )
         * */


        //处理一下角度问
                /**
                 * 为什么要这样处理?
                 * 因为我们看上去认为的角度跟实际上圆角的角度有90度的差距。
                 * 例如对于零度来说,在我们的圆形是 | 一条垂直的竖线就是零度了,但对于实际计算这个已经是902、度了。
                 * **/
        var Angle0=angle;
        Angle0=360+angle-90;
        Angle0=Angle0%360;

        _res.x= _d_data.radiusPoint.x+appData.rx*Math.cos(Angle0*Math.PI/180);
        _res.y= _d_data.radiusPoint.y+appData.rx*Math.sin(Angle0*Math.PI/180);
        //--注意,这个得到的坐标是以正常的坐标系,即,左下角x,从左到右为x,从下到上为y,现在这个不是,现在的页面的坐标系是从上到下才是y轴,y轴要处理一下。


        return _res;
      }
      ,setPercent:function(percent){
        var me=this;
        var _d_str=me.caculateD(percent);
        //_el_path.d=_d_str;
        $(_el_path).attr("d",_d_str);
      }
      ,setAngle:function(angle){
        var me=this;
        var _d_str=me.caculateDbyAngle(angle);
        //_el_path.d=_d_str;
        $(_el_path).attr("d",_d_str);
      }
    };


    app.init();

    var returnObject={
      setPercent:function(percent){
        app.setPercent(percent);
      }
      ,setAngle:function(angle){
        app.setAngle(angle);
      }

    };

    return returnObject;
  };
  var _loading={};
  function InitSVGLoading(){
    _loading=SVGLoading({
      container:$("#container")
    });
  };
  InitSVGLoading();
  var _current_percent=0;
 setInterval(function(){
    _loading.setPercent(_current_percent);
    _current_percent=_current_percent+0.1;
    _current_percent=_current_percent%100;

  },10);
</script>
</body>
</html>

jquery.js和laytpl.js请在网上下载。

效果

这里写图片描述

这里写图片描述

兼容性

大家别执着于兼容性了,ie6-9都恐怕没办法运行,但是,ios,安卓【假如不是古董级别】,chrome,safari,firefox都可以运行,作为一名开发html5的前端,这个兼容性还不够么。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值