You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为React-Konva的Image元素添加圆角

为React-Konva图片添加圆角的可行方案

Konva的KonvaImage组件本身没有直接的cornerRadius属性,需要通过裁剪方式实现圆角效果,以下是两种稳定可行的方案:

方案一:使用Group的clipFunc实现动态圆角裁剪

这是性能最优且适配拖拽、缩放场景的方案,通过给包裹图片的Group定义裁剪路径,实现圆角效果:

const URLImage = ({ image, isSelected, onSelect, onTransform }) => {
  const imageRef = useRef();
  const trRef = useRef();
  const [img] = useImage(image.src);

  // 定义圆角裁剪路径函数
  const clipFunc = (ctx) => {
    const displayWidth = image.width * image.scaleX;
    const displayHeight = image.height * image.scaleY;
    const cornerRadius = 20; // 可按需调整圆角大小

    // 绘制圆角矩形路径
    ctx.beginPath();
    ctx.moveTo(cornerRadius, 0);
    ctx.lineTo(displayWidth - cornerRadius, 0);
    ctx.quadraticCurveTo(displayWidth, 0, displayWidth, cornerRadius);
    ctx.lineTo(displayWidth, displayHeight - cornerRadius);
    ctx.quadraticCurveTo(displayWidth, displayHeight, displayWidth - cornerRadius, displayHeight);
    ctx.lineTo(cornerRadius, displayHeight);
    ctx.quadraticCurveTo(0, displayHeight, 0, displayHeight - cornerRadius);
    ctx.lineTo(0, cornerRadius);
    ctx.quadraticCurveTo(0, 0, cornerRadius, 0);
    ctx.closePath();
  };

  useEffect(() => {
    if (isSelected) {
      trRef.current.nodes([imageRef.current]);
      trRef.current.getLayer().batchDraw();
    }
  }, [isSelected]);

  return (
    <Group 
      clipFunc={clipFunc}
      // 将图片的位置属性移到Group上,保证裁剪坐标系对齐
      x={image.middle ? image.x - image.width / (2 / image.scaleX) : image.x}
      y={image.middle ? image.y - image.height / (2 / image.scaleY) : image.y}
    >
      <KonvaImage
        ref={imageRef}
        image={img}
        x={0}
        y={0}
        width={image.width}
        stroke="rgba(255, 255, 255, 0.1)"
        strokeWidth={1}
        height={image.height}
        scaleX={image.scaleX}
        scaleY={image.scaleY}
        draggable={image.draggable}
        onClick={onSelect}
        onTap={onSelect}
        onDragEnd={(e) => {
          image.middle = false;
          // 更新Group的位置而非图片自身位置
          image.x = e.target.parent.x();
          image.y = e.target.parent.y();
        }}
        onTransformEnd={(e) => {
          image.middle = false;
          image.x = e.target.parent.x();
          image.y = e.target.parent.y();
          image.scaleX = e.target.scaleX();
          image.scaleY = e.target.scaleY();
          onTransform();
        }}
      />
      {isSelected && <Transformer ref={trRef} />}
    </Group>
  );
};

关键修改说明:

  • 把图片的x/y位置属性迁移到外层Group,确保裁剪路径和图片显示区域对齐
  • 通过clipFunc绘制圆角矩形路径,对Group内的图片进行裁剪
  • 拖拽、变换结束时,更新Group的位置而非图片自身位置

方案二:使用Rect作为蒙版(适合固定尺寸场景)

如果图片尺寸相对固定,可使用带圆角的Rect作为蒙版,将图片设为矩形的填充图案:

const URLImage = ({ image, isSelected, onSelect, onTransform }) => {
  const rectRef = useRef();
  const trRef = useRef();
  const [img] = useImage(image.src);

  useEffect(() => {
    if (isSelected) {
      trRef.current.nodes([rectRef.current]);
      trRef.current.getLayer().batchDraw();
    }
  }, [isSelected]);

  return (
    <Group>
      <KonvaRect
        ref={rectRef}
        x={image.middle ? image.x - image.width / (2 / image.scaleX) : image.x}
        y={image.middle ? image.y - image.height / (2 / image.scaleY) : image.y}
        width={image.width * image.scaleX}
        height={image.height * image.scaleY}
        cornerRadius={20}
        fillPatternImage={img}
        fillPatternScaleX={1 / image.scaleX}
        fillPatternScaleY={1 / image.scaleY}
        stroke="rgba(255, 255, 255, 0.1)"
        strokeWidth={1}
        draggable={image.draggable}
        onClick={onSelect}
        onTap={onSelect}
        onDragEnd={(e) => {
          image.middle = false;
          image.x = e.target.x();
          image.y = e.target.y();
        }}
        onTransformEnd={(e) => {
          image.middle = false;
          image.x = e.target.x();
          image.y = e.target.y();
          image.scaleX = e.target.scaleX();
          image.scaleY = e.target.scaleY();
          onTransform();
        }}
      />
      {isSelected && <Transformer ref={trRef} />}
    </Group>
  );
};

注意事项:

  • 需要设置fillPatternScale抵消矩形的缩放比例,避免图片拉伸变形
  • 频繁缩放场景下,该方案性能略低于方案一

内容的提问来源于stack exchange,提问作者Anay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 23:42:48