我想做什么:
我想使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组件沿着移动。
我观察到的事情:
- 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;
1条答案
按热度按时间2ul0zpep1#
由于top和left属性不起作用,我简单地替换了以下代码:
有以下几点(它改进了一点):
我使用了
marginTop
和marginLeft
,并删除了margin
。其次,
x
应该与marginLeft
搭配,y
应该与marginTop
搭配,所以我也更正了这一点。