扩展JFlow

可以从以下几处扩展JFlow:

绘图单元

通过继承 Node 或者 BaseLink,实现必要的方法,来拓展绘图单元,比如实现三角箭头:

import { Node } from '@joskii/jflow';
// 夹角为 90 度好了 1/sqrt(2)
const cosAngle = 0.7071;
const sinAngle = 0.7071;
class Angle extends Node {
    constructor(configs) {
        super(configs);
        this.wing = configs.wing || 6;
        this.rotation = configs.rotation || 0;
        this._cacheWingPoint();
    }
    // Vue 插件调用这个方法来更新配置
    setConfig(configs) {
        Object.keys(configs).forEach((k) => {
            if (configs[k] !== undefined && configs[k] !== null) {
                this[k] = configs[k];
            }
        });
        if (this.wing !== configs.wing) {
            this._cacheWingPoint();
        }
    }

    _cacheWingPoint() {
        const w = this.wing;
        const y = w * cosAngle / 2;
        const x = w * sinAngle;
        this.width = x * 2;
        this.height = x * 2;
        this._cachePoints = [
            [x, -y],
            [0, y],
            [-x, -y],
        ];
    }

    // JFlow 绘制函数,入参是 CanvasRenderingContext2D
    render(ctx) {
        ctx.save();
        ctx.beginPath();

        const [x, y] = this.anchor;
        const [a, b, c] = this._cachePoints;
        const rotateInRadios = this.rotation * Math.PI / 180;
        ctx.translate(x, y);
        ctx.rotate(rotateInRadios);
        ctx.moveTo(a[0], a[1]);
        ctx.lineTo(b[0], b[1]);
        ctx.lineTo(c[0], c[1]);
        if (this.borderWidth && this.borderColor) {
            ctx.lineWidth = this.borderWidth;
            ctx.strokeStyle = this.borderColor;
            ctx.stroke();
        }
        ctx.rotate(-rotateInRadios);
        ctx.translate(-x, -y);
        ctx.restore();
    }

    // 鼠标点击检测,point已换算成当前组坐标系下的坐标了
    isHit(point) {
        return false;
    }
    // 最小外接矩形,矩形使用左上顶点和右下顶点表示
    getBoundingRect() {
        const anchor = this.anchor;
        const w = this.width / 2;
        const h = this.height / 2;
        const ltx = anchor[0] - w;
        const lty = anchor[1] - h;
        const rbx = anchor[0] + w;
        const rby = anchor[1] + h;
        return [
            ltx, lty,
            rbx, rby,
        ];
    }
    // 维度
    getBoundingDimension() {
        return {
            height: this.height,
            width: this.width,
        };
    }
}

当然也可以通过继承已有的一些形状来省略部分方法的实现,比如实现一个三个点的按钮

import { Rectangle } from '@joskii/jflow';
// 继承了 Rectangle,复用了会矩形的设定
class Dot3 extends Rectangle {
    constructor(configs) {
        super(configs);
        this.width = 4;
        this.height = 14;
    }

    setConfig(configs) {
        Object.keys(configs).forEach((k) => {
            if (configs[k] !== undefined && configs[k] !== null) {
                this[k] = configs[k];
            }
        });
    }

    render(ctx) {
        ctx.save();
        ctx.beginPath();

        const [x, y] = this.anchor;
        ctx.fillStyle = this.backgroundColor;
        ctx.arc(x, y - 5, 1, 0, 2 * Math.PI);
        ctx.arc(x, y, 1, 0, 2 * Math.PI);
        ctx.arc(x, y + 5, 1, 0, 2 * Math.PI);
        ctx.fill();
        ctx.restore();
    }
}
export default Dot3;

在Vue中,可以在通过插件配置注入新的组件

Vue.use(JFlowVuePlugin, {
    custom: {
        Angle,
        Dot3,
    },
});

之后就可以在工程中通过标签正常使用了,configs传入对象具体的setConfigs函数

<template>
    <j-angle :configs="{
        wing: 6,
        borderWidth: 1.5,
        borderColor: '#999',
        rotation: 180,
    }"></j-angle>
</template>
<template>
    <j-dot3 :configs="{
        backgroundColor: '#323747',
    }"></j-dot3>
</template>

拓展组

通过 GroupFactory 来拓展组,如下:

// 拓展 Diamond 形状为一个组
GroupFactory(Diamond, {
    // shapeShift 是 shapeshiftbox
    // 这里定义了该层的宽高,是基于内部paddingbox的宽高来计算。
    shapeShift(width, height) {
        return [width + height * 0.28865, height]
    }
});

点线布局和组布局

参考

事件监听策略

通过自定义事件映射关系来满足不同的交互需求。默认的交互为 https://github.com/wt911122/JFlow/blob/90deff93a65b84a9664b88a929066ed4b8f14e7f/src/core/events/adapter.js#L18

自定义事件监听策略可参考 https://github.com/wt911122/JFlow/blob/master/src/core/events/commonAdapter.js 来制定。

继续了解

内部性能优化