使用svg画圆环

 

项目中需要一个圆形进度条,本着能省则省的原则,先去elementui上看了下,傻眼了,不一样,ui直接否定了这个办法。这个是设计,这个是elementui上面的,差很多吗?yes!

去百度了发现自己画一个也不是很费事,经过一番思想建设,对,就是在想ui为啥要求这么严格,哈哈哈,开干!

先画了个差不多的,两个圆圈简单点,代码如下:

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" version="1.1"
xmlns="http://www.w3.org/2000/svg">
<circle cx="60" cy="60" r="40" fill="RGB(222,212,238)" />
<circle cx="60" cy="60" r="32" stroke="#F5003C"
stroke-width="8" fill="RGB(222,212,238)"/>
</svg>

这个没啥难点,cx,cy,r分别表示圆心(x,y)和半径r,stroke-width是圆的边,stroke表示边的颜色,fill表示整个圆的填充颜色。其实就是两个同心圆,里面的圆的边带有一定的宽度,展现出来效果就是上面这样了。

下面开始难点的,就是进度不是100%时,只是一段圆弧的情况。

圆弧计算图示怕说不明白,画了个图示一下。

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg width="100%" height="100%" version="1.1"
xmlns="http://www.w3.org/2000/svg">
<circle cx="40" cy="40" r="40" fill="RGB(222,212,238)" />
<path d="M 40 8 A 32 32, 0, 0, 1, 40,72" stroke="#F5003C" stroke-width="8" fill="RGB(222,212,238)" />
</svg>

上面的path就是画弧线的指令,d="M 40 8 A 32 32, 0, 0, 1, 40,72",d="M 起点x 起点y A 圆心x 圆心y, 0, 0(画小弧), 1,终点x, 终点y“。加上文字,text标签,之前不知道,以为只能有一个text,后来发现可以有无数个,前提是装得下,字体的样式,就是css中,font的各个属性直接添加在标签上。

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg width="100%" height="100%" version="1.1"
xmlns="http://www.w3.org/2000/svg">
<circle cx="40" cy="40" r="40" fill="RGB(222,212,238)" />
<path d="M 40 8 A 32 32, 0, 0, 1, 40,72" stroke="#F5003C" stroke-width="8" fill="RGB(222,212,238)" />
<text x="25" y="48" fill="green" font-size="20" font-style="italic">55</text>
<text x="50" y="48" fill="green" font-size="13" font-style="italic">%</text>
</svg>

 

下面附上我用vue写的一个组件,里面外层圆大小只计算了80,60两种,项目中是够用了。

<template>
    <div class="contain-c-progress">
        <svg :id="cid" :width="cwidth" :height="cwidth" version="1.1" xmlns="http://www.w3.org/2000/svg">
            <circle :cx="cr.cx" :cy="cr.cy" :r="bgr" :fill="bg" />
            <path v-if="percent!=100" :d="cd" :stroke="strokeColor" :stroke-width="strokeWidth" :fill="bg" />
            <circle v-if="percent==100" :cx="cr.cx" :cy="cr.cy" :r="r" :stroke="strokeColor" :stroke-width="strokeWidth" :fill="bg" />
            <text :x="textPos.x" :y="textPos.y" :fill="strokeColor" :font-size="fontSize.f0" font-style="italic">{{percent}}</text>
            <text :x="textPos.x1" :y="textPos.y1" :fill="strokeColor" :font-size="fontSize.f1" font-style="italic">%</text>
        </svg>
    </div>
</template>

<script type="text/ecmascript-6">
export default {
  name: "Cprogress",
  data() {
    return {};
  },
  props: {
    cw: {
      required: true,
      type: Number
    },
    id: {
      required: true,
      type: Number
    },
    bg: {
      required: true,
      type: String
    },
    strokeColor: {
      type: String,
      required: true
    },
    strokeWidth: {
      type: Number,
      required: true
    },
    percent: {
      type: Number,
      required: true
    }
  },
  computed: {
    //整个svg的大小
    cwidth() {
      return this.cw + "px";
    },
    //path的起点
    start() {
      if (this.cw == 80) {
        return { sx: 40, sy: 8 };
      } else {
        return { sx: 30, sy: 6 };
      }
    },
    //背景圆的半径
    bgr() {
      return this.cw / 2;
    },
    //弧线半径
    r() {
      return this.cw==80? this.cw / 2 - 8 : this.cw/2 -6;
    },
    //弧线的圆心
    cr() {
      return { cx: this.cw / 2, cy: this.cw / 2 };
    },
    //path 终点
    end() {
      //终点位置
      var alpha = this.percent / 100 * 2 * Math.PI;
      var ex = this.cw / 2 + this.r * Math.sin(alpha);
      var ey = this.cw / 2 - this.r * Math.cos(alpha);
      return { x: ex, y: ey };
    },
    cd() {
      //示例:"M50 10 A 40 40, 0, 0, 1, 50  90"
      return this.percent <= 50
        ? `M ${this.start.sx} ${this.start.sy} 
              A ${this.r} ${this.r}, 0, 0, 1,${this.end.x} ${this.end.y}`
        : `M ${this.start.sx} ${this.start.sy}
              A ${this.r} ${this.r}, 0, 1, 1,${this.end.x} ${this.end.y}`;
    },
    cid() {
      //svg的id
      return "svg" + this.id;
    },
    textPos() {
      //文字x方向位置
      if (this.cw == 80) {
        if (this.percent < 10) {
          return { x: 30, y: 48, x1: 43, y1: 48};
        } else if (this.percent < 100) {
          return { x: 22, y: 48, x1: 47, y1: 48};
        } else {
          return { x: 14, y: 48, x1: 51, y1: 48 };
        }
      } else {
        if (this.percent < 10) {
          return { x: 22, y: 37, x1: 33, y1: 37 };
        } else if (this.percent < 100) {
          return { x: 12, y: 37, x1: 33, y1: 37 };
        } else {
          return { x: 8, y: 37, x1: 38, y1: 37 };
        }
      }
    },
    //文字大小
    fontSize(){
      if(this.cw==80){
        return {f0: 20, f1: 13}
      }else if(this.cw==60){
        return {f0: 16, f1: 12}
      }
    }
  }
};
</script>

<style scoped>
svg {
  text-align: center;
  line-height: 100px;
  color: #fff;
}
</style>
<cprogress :cw="80" :id="index" :stroke-width='8' stroke-color="#F62256" bg="#FFDDDD"
                            :percent="100"></cprogress>

最终显示效果:

溜了溜了,设计要来找我了 

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值