Logicflow箭头自定义demo

535 阅读4分钟

流程图的绘制中,箭头用来表示步骤或过程的方向,对于整个流程图所表达的逻辑起着至关重要的作用,对于不同风格的流程图在箭头的大小、颜色、形状上有着不同的诉求,因此自定义箭头可以极大的丰富流程图的表达。

方式选择

下面介绍了3中自定义箭头的方式,如何选择自己更适合哪种方式呢?

  1. 选择方式一:如果觉得当前的箭头大小不合适,指向修改下大小,那就选择方式一,成本低只用设置下主题。
  2. 选择方式二:如果觉得不光大小不合适,颜色也不是你想要的,那就选择方式二,这个需要自定义连线,复写箭头样式方法。
  3. 选择方式三:如果觉得箭头的形状不是你想要的,需要自定义形状,那就选择方式三,需要自定义连线以及箭头方法,demo中列举了集中常见的箭头path,拿去用就行。如果是设计了独有的箭头,如果是svg参考下面的代码把svg中各个属性替换到里面就行。如果是图片参考下面的代码替换图片地址就行。

demo线上地址:xinxin93.github.io/logicflow_a…

demo代码:github.com/xinxin93/lo…

Logicflow箭头源码分析:juejin.cn/post/716391…

方式一:自定义箭头大小

如果只想修改箭头的大小,可以通过设置主题进行设置。

lf.setTheme({ 
  arrow: {
    offset: 20, // 箭头垂线长度
    verticalLength: 4, // 箭头底线长度
  }
})

image.png

方式二:自定义箭头颜色

箭头颜色默认是跟随连线的颜色的,如果想要自定义箭头颜色,可以通过复写getArrowStyle进行修改。

import { PolylineEdge, PolylineEdgeModel } from '@logicflow/core';




class View extends PolylineEdge {
  getArrowStyle() {
    const style = super.getArrowStyle();
    return {
      ...style,
      fill: 'green',
      stroke: 'green',
    }
  }
}




export function registerPolyline(lf) {
  lf.register({type: 'polyline', view: View, model: PolylineEdgeModel})

image.png

方式三:自定义箭头图形

自定义箭头图形复写getEndArrow实现,箭头图形可以通过svg的path标签、image标签进行自定义。我的示例代码中实现了多种箭头图形样式,具体展示哪种箭头properties属性中进行定义,因此整个getEndArrow函数非常大,如果你的需求只会有一种箭头样式可以简化代码,不用在properties中判断要展示哪种直接返回要展示的图形就可以。

class View extends PolylineEdge {
  getEndArrow() {
    const { model } = this.props;
    const { id, properties } = model;
    const { stroke, strokeWidth } = this.getArrowStyle();
    const { arrowEnd } = properties;
    let pathAttr = {
      stroke,
      strokeWidth,
    }
    // ArrorLis 枚举在最下面给出
    pathAttr = arrowEnd ? {...pathAttr, ...ArrorList[arrowEnd]} : {...pathAttr, ...ArrorList['2']};
    if (pathAttr.type === 'custome1') {
      return  h('svg', { x: -28, y: -15,  width: 30, height: 30, viewBox: "0 0 1024 1024"}, [
        h('path', {
          d: 'M0.1 884.5l1024-372.4H279.4L0.1 884.5z',
          fill: '#2868F0',
        }),
        h('path', {
          d: 'M279.4 512.1h744.7L0.1 139.8l279.3 372.3z',
          fill: '#043EB8',
        }),
      ]);
    } else if (pathAttr.type === 'custome2') {
      return  h('image', {
        x: -17,
        y: -10,
        width: 20,
        height: 20,
        xlinkHref: 'src/assets/custome2.png'
      })
    } else if (pathAttr.type === 'custome3') {
      return  h('image', {
        x: -23,
        y: -15,
        width: 30,
        height: 30,
        xlinkHref: 'src/assets/custome3.png',
      })
    } else if (pathAttr.d) {
      if (pathAttr.fill) {
        pathAttr.fill = stroke
      } else if (pathAttr.fillColor){
        pathAttr.fill = pathAttr.fillColor
      } else {
        pathAttr.fill = 'none'
      }
      return (
        h('path', { ...pathAttr })
      )
    } else {
      return (
        h(pathAttr.tag, { ...pathAttr, ...pathAttr.tagAttr })
      );
    }
  }
}

image.png

自定义起点箭头

起点的箭头默认是不展示的,在连线view的getArrow中已经定义了起点箭头,在model中没有给出其定义,因此未展示。想要展示起点箭头,需要在model中定义起点的id。关于起点箭头图形的自定义与上面提到的终点箭头自定义是类似的,不过起点和终点箭头如果图形是一样的话,可以通过设置相同的path,然后旋转180度实现。

class Model extends PolylineEdgeModel {
  // 展示起点箭头
  setAttributes() {
    const { properties } = this;
    if (properties.arrowStart) {
      this.arrowConfig.markerStart = `url(#marker-start-${this.id})`
    }
  }
}




class View extends PolylineEdge {
  getStartArrow() {
    const { model } = this.props;
    const { id, properties } = model;
    const { stroke, strokeWidth } = this.getArrowStyle();
    const { arrowStart } = properties;
    let pathAttr = {
      stroke,
      strokeWidth,
      transform: 'rotate(180)'
    }
    // ArrorLis 枚举在最下面给出
    pathAttr = arrowStart ? {...pathAttr, ...ArrorList[arrowStart]} : {...pathAttr, ...ArrorList['1']};
    console.log(pathAttr);
    if (pathAttr.type === 'custome1') {
      return  h('svg', { x: 2, y: -15,  width: 30, height: 30, viewBox: "0 0 1024 1024"}, [
        h('g', { transform: 'translate(1024 1024) rotate(180)'}, [
          h('path', {
            d: 'M0.1 884.5l1024-372.4H279.4L0.1 884.5z',
            fill: '#2868F0',
            
          }),
          h('path', {
            d: 'M279.4 512.1h744.7L0.1 139.8l279.3 372.3z',
            fill: '#043EB8',
          }),
        ]),
      ]);
    } else if (pathAttr.type === 'custome2') {
      return  h('image', {
        x: -17,
        y: -10,
        width: 20,
        height: 20,
        xlinkHref: 'src/assets/custome2.png',
        transform: 'rotate(180)'
      })
    } else if (pathAttr.type === 'custome3') {
      return  h('image', {
        x: -23,
        y: -15,
        width: 30,
        height: 30,
        xlinkHref: 'src/assets/custome3.png',
        transform: 'rotate(180)'
      })
    } else if (pathAttr.d) {
      if (pathAttr.fill) {
        pathAttr.fill = stroke
      } else if (pathAttr.fillColor){
        pathAttr.fill = pathAttr.fillColor
      } else {
        pathAttr.fill = 'none'
      }
      return (
        h('path', { ...pathAttr })
      )
    } else {
      return (
        h(pathAttr.tag, { ...pathAttr, ...pathAttr.tagAttr })
      );
    }
  

image.png

 

自定义箭头path枚举

前面自定义箭头方式三示例中用到的path示例

// 自定义箭头path枚举列表
export const ArrorList =  {
  1: {},
  2: {
    d: 'M 0 0 -10 -5 -10 5 z',
    fill: true,
  },
  3: {
    d: 'M 0 0 -10 5',
  },
  4: {
    d: 'M -10 0  -20 -5 -30 0 -20 5 z',
    fill: true
  },
  5: {
    d: 'M 0 0 -10 -5 -10 5 z',
    fillColor: '#f7f9ff',
  },
  6: {
    d: 'M -10 -5 0 0 -10 5',
  },
  7: {
    d: 'M -10 0  -20 -5 -30 0 -20 5 z',
    fillColor: '#f7f9ff',
  },
  8: {
    tag: 'circle',
    tagAttr: {
      cx: -10,
      cy: 0,
      r: 5,
      fill: '#f7f9ff',
    },
  },
  101: { type: 'custome1'},
  102: { type: 'custome2'},
  103: { type: 'custome3'}
}