首先,谢谢您抽出宝贵的时间回答我的问题。
我正在基于konva.js进行反应的小型图像编辑器项目中工作。但是我遇到了一些问题,这些问题困扰了我几天。 我想使用组的旋转属性来旋转该组及其中的所有形状,当单击“旋转”按钮时,它可以正常工作,但是当我单击文本按钮,并想在图像上绘制它并重新定位时确切地说,pic1是我的预期结果,但实际上,我得到了意外的结果,显示为pic2,我该怎么做才能精确旋转组和其中的所有形状。
我的简单示例如下:
class Test extends React.Component{
constructor(props) {
super(props)
this.state = {
historyArray: [],
isTexting: true,
image: new window.Image(),
layerPos:{
x: 300,
y: 100,
},
imageWidth: 0,
imageHeight: 0,
rotateDegrees: 0,
}
}
componentDidMount() {
const {historyArray} = this.state;
this.state.image.setAttribute("crossOrigin", "anonymous");
this.state.image.src = "https://vd.youniwote.com/homework/44evmey2cbd/submit/44evmey2cbe.jpg";
this.state.image.onload = () => {
let imageWidth = this.state.image.width > 620 ? 620 / (parseFloat(this.state.image.height) / parseFloat(this.state.image.width)) : this.state.image.width;
let imageHeight = this.state.image.height > 620 ? 620 : this.state.image.height;
let imageObj = {
mode: 'image',
image: this.state.image,
width: imageWidth,
height: imageHeight,
}
historyArray.push(imageObj);
this.setState({
historyArray,
imageWidth,
imageHeight,
})
}
}
clickStage = (event) => {
const {mode, isTexting, historyArray} = this.state;
if (mode == 'text') {
if (isTexting) {
let textarea = document.createElement('textarea');
document.body.appendChild(textarea);
textarea.style.position = 'absolute';
textarea.style.top = event.evt.pageY + 'px';
textarea.style.left = event.evt.pageX + 'px';
textarea.style.width = 100;
textarea.focus();
this.setState({
isTexting: false,
})
textarea.addEventListener('keydown', (e) => {
if (e.keyCode === 13) {
historyArray.push({
mode: "text",
x:this.getActualPosInStage(event).x,
y: this.getActualPosInStage(event).y,
text: textarea.value,
})
document.body.removeChild(textarea);
this.setState({
isTexting: true,
historyArray
})
}
});
}
}
}
getActualPosInStage = (e) => {
const {layerPos} = this.state;
let stageBox = this.stage.getStage().getContainer().getBoundingClientRect();
let mousePos = {
x: e.evt.clientX,
y: e.evt.clientY,
}
let x = Math.abs(mousePos.x - stageBox.left - layerPos.x);
let y = Math.abs(mousePos.y - stageBox.top - layerPos.y);
return {x,y}
}
render() {
return (
<div>
<div style={{top: 0, left: 0}}>
<Button onClick={() => {
this.setState({
mode: 'text',
groupDraggable: false,
})
}}>Text</Button>
<Button style={{marginLeft: 20}} onClick={() => {
const {rotateDegrees} = this.state;
this.setState({
rotateDegrees: rotateDegrees + 90,
groupDraggable: false,
mode: 'rotate',
})
this.group.offsetX(this.group.width() / 2);
this.group.offsetY(this.group.height() / 2);
this.group.x(this.group.width() / 2);
this.group.y(this.group.height() / 2);
}}>Rotate</Button>
</div>
<Stage
onClick={(e) => {this.clickStage(e)}}
width={1000}
height={1000}
ref={node => {
this.stage = node;
}}
>
<Layer
x={this.state.layerPos.x}
y={this.state.layerPos.y}
ref={node => {
this.layer = node;
}}
>
<Group
rotation={this.state.rotateDegrees}
width={this.state.imageWidth}
height={this.state.imageHeight}
ref={node => {
this.group = node;
}}
>
{
this.state.historyArray.map((item, index) => {
if (item.mode == 'image') {
return (
<Image
key={index}
width={item.width}
height={item.height}
image={this.state.image}
ref={node => {
this.imageNode = node;
}}
/>
)
} else if (item.mode == 'text') {
return(
<Text
key={index}
x={item.x}
y={item.y}
text={item.text}
fontSize={24}
fill='red'
/>
)
}
})
}
</Group>
</Layer>
</Stage>
</div>
)
}
}
这些问题困扰了我几天,如果有人可以回答我的问题,我会提出来
答案 0 :(得分:1)
作为文本的位置,您需要使用相对于组的位置。在代码中,您使用的是相对于舞台左上角的位置。由于您的小组已移动和旋转,因此结果不正确。
因此,您需要计算相对于组的位置。简单的方法是将组的绝对变换矩阵求逆并应用于鼠标点:
const stage = e.target.getStage();
const pos = stage.getPointerPosition();
const absTransform = this.group.getAbsoluteTransform();
const invertedTransform = new Konva.Transform(
absTransform.getMatrix()
).invert();
const shapePos = invertedTransform.point(pos);
答案 1 :(得分:0)