SVG ---- 在流程图/类图中 使用二次贝塞尔曲线 画出漂亮的箭头

1 篇文章 0 订阅
1 篇文章 0 订阅

Foreword

在最近做的项目中遇到了画 UML 类图,其中想画一根比较好看的曲线,而不是笔直笔直的直线,于是查了很多,得知关于贝塞尔曲线,在这里做一下记录。
如果你想要深入了解,你可以看一下张鑫旭的 深度掌握SVG路径path的贝塞尔曲线指令

下面先上一效果图:
贝塞尔曲线


看一下如何实现

图片来自网络

  • 看一下如何画出二次贝塞尔曲线
<path :d="`M${x0},${y0} Q${(x1},${y1} ${x2},${y2} T${x4},${y4}`"
      stroke="#4CAF50" fill="none" style="stroke-width: 1px;" class="arrow_line a_line"></path>
  • 看一下代码重点看一下坐标 x0,y0 x1,y1 x2,y2 x4,y4 咱们只需要 四个坐标点 就可以画出比较漂亮的二次贝塞尔曲线,这里结合了 M Q T 三个指令(二次贝塞尔曲线指令)下表是所有的指令
命令名称参数
Mmoveto(x y)+
Zclosepath  关闭路径(none)
Llineto  画线到(x y)+
Hhorizontal lineto  水平线到x+
Vvertical lineto  垂直线到y+
Ccurveto  三次贝塞尔曲线到(x1 y1 x2 y2 x y)+
Ssmooth curveto  光滑三次贝塞尔曲线到(x2 y2 x y)+
Qquadratic Bézier curveto  二次贝塞尔曲线到(x1 y1 x y)+
Tsmooth quadratic Bézier curveto  光滑二次贝塞尔曲线到(x y)+
Aelliptical arc  椭圆弧(rx ry x-axis-rotation large-arc-flag sweep-flag x y)+
RCatmull-Rom curveto*  Catmull-Rom曲线x1 y1 (x y)+
  • 如果你只想画出一个漂亮的曲线的话,上表中的内容不重要,在这里需要首先知道自己想要怎么样的曲线,如下图,这是我想要的:在这里插入图片描述
  • 那么我要画出这条曲线只需要知道四个坐标,即起点、总长度的1/4处、总长度的1/2处、终点即可

在这里插入图片描述


看一下代码吧

  • 如果你刚好使用 vue 那你大可以直接复制下面的箭头组件到你的项目
  • 但是如果你转发了本篇文章或者下面的代码,请注明出处,都不容易~~ 谢谢了
<template>
  <g class="arrow">
    <defs>
      <marker id='tp_arrow' refX='0' refY='0' markerWidth='12' markerHeight='12' orient='auto' viewBox='0, -4, 12, 12' >
        <path d='M0 -4 L0 4 L10 0' style='fill:#4CAF50' stroke-width='0'></path>
      </marker>
    </defs>

    <!--  直线 ---- 扩大选择区域  -->
    <g v-if="lineType=='line'">
      <polyline :points='`${fromX},${fromY} ${toX},${toY}`' style='stroke:transparent;stroke-width:10;'></polyline>
      <polyline class="arrow_line" type='step' :points='`${fromX},${fromY} ${toX},${toY}`' style='stroke:#4CAF50;stroke-width:1;' marker-end="url(#tp_arrow)" ></polyline>
    </g>


    <!--  如果想使曲线更加弯曲 可以 Q的第一个参数可以设置为 5*fromX+3*toX)/8  -->
    <!--  贝塞尔曲线 ---- 扩大选择区域  -->
    <g v-if="lineType=='bezier'">
      <path :d="`M${fromX},${fromY} Q${(3*fromX+toX)/4},${fromY} ${(toX+fromX)/2},${(toY+fromY)/2} T${toX},${toY}`" stroke="transparent" fill="none"
            style="stroke-width: 10px;" class="a_line"></path>
      <path :d="`M${fromX},${fromY} Q${(3*fromX+toX)/4},${fromY} ${(toX+fromX)/2},${(toY+fromY)/2} T${toX},${toY}`" marker-end="url(#tp_arrow)"
            stroke="#4CAF50" fill="none" style="stroke-width: 1px;" class="arrow_line a_line"></path>
    </g>

    <!--  删除的叉号❌  -->
    <g class="arrow_cross" v-if="!moveMode" :transform="`translate(${(toX-fromX)/2 + fromX-6},${(toY-fromY)/2 + fromY-6})`" @click="delArrow">
      <rect width="12" height="12" style="fill: transparent"></rect>
      <polyline style="stroke:rgba(214, 0, -1, 1);stroke-width:2" points="0 0 12 12"></polyline>
      <polyline style="stroke:rgba(214, 0, -1, 1);stroke-width:2" points="12 0 0 12"></polyline>
    </g>

  </g>
</template>


<script>
  /**
   * 箭头组件
   * powered by pancras
   * 2019年11月5日
   **/

  export default {
    components: {},
    props:{
      fromX:{
        type:Number,
        default(){ return 0 }
      },
      fromY:{
        type:Number,
        default(){ return 0 }
      },
      toX:{
        type:Number,
        default(){ return 0 }
      },
      toY:{
        type:Number,
        default(){ return 0 }
      },

      /**
       * 箭头的格式 直线/贝塞尔曲线
       *  bezier / line
       * **/
      lineType:{
        type:String,
        default(){ return 'bezier' }
      },

      // 移动模式下隐藏 叉号
      moveMode:{
        type:Boolean,
        default(){ return false }
      },
    },
    data() {
      return {
        showCross:false,

      }
    },
    async mounted() {
    },
    methods: {

      // 删除回调
      delArrow(){
        // console.log('umlArrow.vue:触发了删除箭头事件')
        this.$emit('delArrow');
      }
    }

  }
</script>
<style scoped>
  .arrow:hover .arrow_cross{display: block;}
  .arrow_cross{display: none;cursor: pointer;transition: .2s ease all;}

  .a_line{transition: .2s all ease;}
</style>

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue2 使用 `<svg-icon/>` 组件,需要先安装 `svg-sprite-loader` 和 `svg4everybody` 依赖。 1. 安装依赖 ```bash npm install svg-sprite-loader svg4everybody --save-dev ``` 2. 创建 `svg` 文件夹,放置 `svg` 图标文件 3. 在 `vue.config.js` 文件配置 `svg-sprite-loader` ```js module.exports = { chainWebpack: config => { const svgRule = config.module.rule('svg'); // 清除已有的所有 loader。 // 如果你不这样做,接下来的 loader 会附加在该规则现有的 loader 之后。 svgRule.uses.clear(); // 添加要使用的 loader svgRule .use('svg-sprite-loader') .loader('svg-sprite-loader') .options({ symbolId: 'icon-[name]' }); } }; ``` 4. 创建 `SvgIcon.vue` 组件 ```vue <template> <svg :class="svgClass" aria-hidden="true" v-on="$listeners"> <use :xlink:href="iconName" /> </svg> </template> <script> export default { name: 'SvgIcon', props: { iconClass: { type: String, required: true }, className: { type: String, default: '' } }, computed: { iconName() { return `#icon-${this.iconClass}`; }, svgClass() { if (this.className) { return 'svg-icon ' + this.className; } else { return 'svg-icon'; } } } }; </script> <style scoped> .svg-icon { width: 1em; height: 1em; vertical-align: -0.15em; fill: currentColor; overflow: hidden; } </style> ``` 5. 在组件使用 `<svg-icon/>` ```vue <template> <div> <svg-icon icon-class="xxx" /> </div> </template> <script> import SvgIcon from '@/components/SvgIcon'; export default { name: 'Example', components: { SvgIcon } }; </script> ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值