我试着用React Konva实现这个HTML文本演示,但是没有用,因为

q5iwbnjs  于 2023-03-06  发布在  React
关注(0)|答案(1)|浏览(146)

我想做什么:

我想使React Konva文本可编辑。也就是说,如果我双击文本...(我可以将其移动到Konva阶段的任何地方)...我可以显示一个文本区域来获取用户的编辑,他/她想对默认文本进行的任何更改。

条件:

  • 回车键(键盘)应产生一个新行。
  • 双击文本应在该文本的相同偏移X和Y上显示该文本区域。
  • 双击div应该返回Text。现在,如果对文本做了任何更改,那么它应该反映在Text组件的标签上
    我尝试用React Konva实现这个HTML文本演示,但是由于限制,我失败了

我想在React Konva中重现的html Konva演示

我做过的事

1.由于HTML 5.0是不兼容的,如果使用与React Konva组件,如文本,图像,正多边形...
1.我使用了'react-konva-utils'中的{ Html },这样我就可以像上面链接中的演示一样将该内容与Text组件沿着移动。

我观察到的事情:

  1. HTML可以使用填充和边距(我们可以在tag.中使用普通的html),但不能使用左上角。
    1.我确实尝试过将Text的X属性放在根div的margin top中,并将Text的Y属性的值放在同一个div的margin left属性中,但我不得不恢复,因为它与上面的演示不太接近。

代码:

import React, { useState, useRef, useEffect, Fragment } from "react";
import { Html } from 'react-konva-utils';
import { Text, Transformer } from "react-konva";
/* 
Konva warning: tr.setNode(shape), tr.node(shape) and tr.attachTo(shape) methods are deprecated. Please use tr.nodes(nodesArray) instead. 
*/
const KText = ({ stage, id, properties, isSelected, onSelect, onChange, setActiveText }) => {
  const shapeRef = useRef();
  const trRef = useRef();
  const [toggleEdit, setToggleEdit] = useState(false)
  useEffect(() => {
    if (isSelected) {
      trRef.current.nodes([shapeRef.current]);
      trRef.current.getLayer().batchDraw();
    }
  }, [isSelected]);
  // console.log("KText", `properties: ${JSON.stringify(properties)}`)
  // console.log("KText", ` properties.text: ${properties.text}`)
  const EditTextField = () => {
    var textProps
    const updateText = (data) => {
      textProps = data
      // console.log("EditTextField", `textProps: ${JSON.stringify(textProps)}`)
    }

    // var mAreaPos = areaPosition()

    const areaPosition = () => {
      let stage1 = stage.current.getStage()
      return ({
        x: stage1.container().offsetLeft + properties.x,
        y: stage1.container().offsetTop + properties.y,
      })
    };

    return (
      <Html >
        <div style={{
          margin: "200px", padding: "20px", background: "lavender",
          borderRadius: 20, borderStyle: "solid", borderColor: "green",
          top: areaPosition().x, left: areaPosition().y
        }}
          onDoubleClick={() => setToggleEdit(!toggleEdit)}>
          <label htmlFor="inputText">Please enter some text below:</label><p>
            <textarea onChange={(evt) => (updateText({ text: evt.target.value, id: id }))}
              id="inputText" name="inputText" rows="4" cols="50" placeholder="Please enter here" />
            <br />
            <button type="text" onClick={() => {
              setToggleEdit(!toggleEdit)
              setActiveText(textProps)
            }}>Close</button>
          </p>
        </div>{/*  */}
      </Html >
    )
  }
  const MainText = () => {
    return (
      <>
        <Fragment>
          <Text
            stroke={"black"}
            strokeWidth={1}
            onTap={onSelect}
            onClick={onSelect}
            onDblClick={() => setToggleEdit(!toggleEdit)}
            ref={shapeRef}
            // {...shapeProps}
            name="text"
            x={properties.x}
            y={properties.y}
            text={properties.text}
            fontFamily={properties.fontFamily}//"Serif"
            fontSize={properties.fontSize}//50
            fontWeight={properties.fontWeight} //"bold"
            fillLinearGradientStartPoint={{ x: 0, y: 0 }}
            fillLinearGradientEndPoint={{ x: 100, y: 100 }}
            fillLinearGradientColorStops={[
              0,
              "rgba(0,0,0,0.7)",
              1,
              "rgba(255,155,255,0.5)"
            ]}
            fillPriority={"linear-gradient"}
            draggable
            onDragEnd={e => {
              /*  onChange({
                  ...shapeProps,
                  x: e.target.x(),
                  y: e.target.y(),
                });*/
            }}
            onTransformEnd={e => {
              // transformer is changing scale
              /*  const node = shapeRef.current;
                const scaleX = node.scaleX();
                const scaleY = node.scaleY();
                node.scaleX(1);
                node.scaleY(1);
                onChange({
                  ...shapeProps,
                  x: node.x(),
                  y: node.y(),
                  width: node.width() * scaleX,
                  height: node.height() * scaleY,
                }); */
            }}
          />
          {isSelected && <Transformer ref={trRef} />}
        </Fragment>
      </>
    )
  }
  const RenderThis = () => {
    let inText = "" + properties.text
    if (inText.trim().length === 0 || toggleEdit) {
      return (
        <EditTextField />
      )
    } else return (
      <MainText />
    )
  }

  // rendering function
  return (
    <RenderThis />
  );
};
export default KText;
2ul0zpep

2ul0zpep1#

由于top和left属性不起作用,我简单地替换了以下代码:

<div style={{
  margin: "200px", padding: "20px", background: "lavender",
  borderRadius: 20, borderStyle: "solid", borderColor: "green",
  top: areaPosition().x, left: areaPosition().y
        }}
  onDoubleClick={() => setToggleEdit(!toggleEdit)}>
...
</div

有以下几点(它改进了一点):
我使用了marginTopmarginLeft,并删除了margin
其次,x应该与marginLeft搭配,y应该与marginTop搭配,所以我也更正了这一点。

<div style={{
   padding: "20px", background: "lavender",
   borderRadius: 20, borderStyle: "solid", borderColor: "green",
   marginTop: areaPosition().y, marginLeft: areaPosition().x
   }}
   onDoubleClick={() => setToggleEdit(!toggleEdit)}>
 ...
</div

相关问题