svg 使用path实现圆角效果

效果图

代码实操 

import React from 'react';
import PropTypes from 'prop-types';
import { iconMaker, triangleMaker } from '../utils';

const Connection = ({ startPoint, radius, height, width, color }) => {
    const [sx, sy] = startPoint;
    // 上下右左, 矩形的四个点
    const point1 = [sx, sy];
    const point2 = [sx, sy + height];
    const point3 = [sx + width, sy + height];
    const point4 = [sx + width, sy];

    // 左边圆角的点坐标
    const cPoint1 = [sx, point2[1] - radius];
    const cPoint2 = point2;
    const cPoint3 = [sx + radius, point2[1]];

    // 右边圆角的点坐标
    const cPoint4 = [point3[0] - radius, point3[1]];
    const cPoint5 = point3;
    const cPoint6 = [point3[0], point3[1] - radius];

    const centerPoint = [
        point2[0] + width / 2,
        point2[1],
        point2[0] + width / 2,
        point2[1] + 20
    ];

    return (
        <g className="pane-node" style={{ stroke: '#4D9DED', strokeWidth: 2 }}>
            <path
                d={`M${cPoint1[0]} ${cPoint1[1]} C ${cPoint1[0]} ${cPoint1[1]}, ${cPoint2[0]} ${cPoint2[1]}, ${cPoint3[0]} ${cPoint3[1]} L ${cPoint4[0]} ${cPoint4[1]}`}
                fill="transparent"
            />
            <circle cx={point1[0]} cy={point1[1]} r="4" fill="#4D9DED" />
            <path d={`${triangleMaker(point4, 12)}`} fill="#4D9DED" />
            <path
                d={`M${cPoint4[0]} ${cPoint4[1]} C ${cPoint4[0]} ${cPoint4[1]}, ${cPoint5[0]} ${cPoint5[1]}, ${cPoint6[0]} ${cPoint6[1]}`}
                fill="transparent"
            />
            <line
                x1={point1[0]}
                y1={point1[1]}
                x2={cPoint1[0]}
                y2={cPoint1[1]}
            />
            <line
                x1={cPoint6[0]}
                y1={cPoint6[1]}
                x2={point4[0]}
                y2={point4[1]}
            />
            <line
                x1={centerPoint[0]}
                y1={centerPoint[1]}
                x2={centerPoint[2]}
                y2={centerPoint[3]}
            />
            {iconMaker([centerPoint[2], centerPoint[3]], 9)}
        </g>
    );
};

Connection.defaultProps = {
    startPoint: [130, 110],
    radius: 4,
    height: 20,
    width: 283,
    color: '#4D9DED'
};

Connection.propTypes = {
    height: PropTypes.number,
    radius: PropTypes.number,
    startPoint: PropTypes.array,
    width: PropTypes.number,
    color: PropTypes.string
};

export default Connection;
export function triangleMaker(startPoint, len) {
    const [x, y] = startPoint;
    return `M${x},${y} L${x - len / 2},${y + len / 2} L${x + len / 2},${
        y + len / 2
    } L${x},${y}`;
}

export function iconMaker(centerPoint, r, stopColor = ['#0073E6', '#66ABF0']) {
    const [x, y] = centerPoint;
    const textLen = Math.floor(r / 3);
    return (
        <g style={{ stroke: '#FFFFFF', strokeWidth: 1 }}>
            <defs>
                <linearGradient id="grad1" x1="0%" y1="0%" x2="0%" y2="100%">
                    <stop
                        offset="0%"
                        style={{ stopColor: stopColor[0], stopOpacity: 1 }}
                    />
                    <stop
                        offset="100%"
                        style={{ stopColor: stopColor[1], stopOpacity: 1 }}
                    />
                </linearGradient>
            </defs>
            <circle cx={x} cy={y} r={r} fill="url(#grad1)" />
            <line
                x1={x - textLen}
                y1={y - textLen}
                x2={x + textLen}
                y2={y + textLen}
            />
            <line
                x1={x + textLen}
                y1={y - textLen}
                x2={x - textLen}
                y2={y + textLen}
            />
        </g>
    );
}

原理解析

c1、c2、c3是p2的贝塞尔曲线控制点

c4、c5、c6是p3的贝塞尔控制点

r为曲线半径 

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值