单击按钮时如何触发事件监听图层上的形状?
How trigger event listening for shapes on a layer when button clicked?
在 KonvaJS 中,是否可以在单击按钮时使层处于非活动状态(但不是不可见),然后在单击另一个按钮时处于活动状态?我已经尝试 "text_overlay.listening(false);" 但它不起作用。我可以使用 "textNode0.listening(false);" 停用单个文本节点,这确实会阻止用户编辑该文本,但这些文本节点位于多边形上,其中一些非常小(例如,欧洲地图上的卢森堡)并且文本区域会阻止用户单击下面的多边形(例如,更改其填充颜色)。此外,将有超过 40 个文本节点需要处理,因此停用 1 层是更可取的!
这是 HTML 文件的按钮部分:
<script src="js/text-input21.js"></script>
<!-- button events -->
<script>
// button states on load
var btnLabelClicked = true;
var btnColorClicked = false;
var btnDrawLinesClicked = false;
//color chip buttons
var btnViolet = document.getElementById("fillViolet");
var btnOrange = document.getElementById("fillOrange");
var btnYellow = document.getElementById("fillYellow");
//color chip buttons' fill when btnLabelClicked = true
btnViolet.style.background = disableBtnFill;
btnOrange.style.background = disableBtnFill;
btnYellow.style.background = disableBtnFill;
var buttonID = 'btnLabel';
function replyClick(clickedID) {
buttonID = (clickedID);
if (buttonID === 'btnColor') {
textNode0.listening(false);
textNode15.listening(false);
textNode16.listening(false);
btnViolet.disabled = false;
btnViolet.style.background = '#842dce';
btnOrange.disabled = false;
btnOrange.style.background = '#ffa500';
btnYellow.disabled = false;
btnYellow.style.background = '#ffff00';
btnLabelClicked = false;
btnColorClicked = true;
btnDrawLinesClicked = false;
} else if (btnColorClicked && (buttonID === 'fillViolet' || buttonID === 'fillOrange' || buttonID === 'fillYellow')) {
//text_overlay.listening(false);
textNode0.listening(false);
textNode15.listening(false);
textNode16.listening(false);
newFill = document.getElementById(buttonID).style.background;
} else if (buttonID === 'btnLabel' || buttonID === 'btnDrawLines' || buttonID === 'btnEraseLines' || buttonID === 'btnExport') {
//disable color buttons
btnColorClicked = false;
btnViolet.disabled = true;
btnViolet.style.background = disableBtnFill;
btnOrange.disabled = true;
btnOrange.style.background = disableBtnFill;
btnYellow.disabled = true;
btnYellow.style.background = disableBtnFill;
if (buttonID === 'btnLabel') {
textNode0.listening(true);
textNode15.listening(true);
textNode16.listening(true);
btnLabelClicked = true;
btnDrawLinesClicked = false;
} else { //buttonID is not btnLabel or any of the color buttons
textNode0.listening(false);
textNode15.listening(false);
textNode16.listening(false);
btnLabelClicked = false;
btnDrawLinesClicked = true;
}
}
}
</script>
这是包含 text_overlay 层的文本-input21.js 文件:
var text_overlay = new Konva.Layer({
listening: true
});
stage.add(text_overlay);
var textNode0 = new Konva.Text({
text: 'X',
x: 80, // centered between Ireland & Great Britain
y: 125,
width: 150,
height: 15,
fontFamily: 'Arial, Helvetica, "sans-serif"',
fontSize: 14,
align: 'center',
listening: true
});
var textNode15 = new Konva.Text({
text: 'X',
x: 230, // Luxembourg
y: 225,
width: 100,
height: 15,
fontFamily: 'Arial, Helvetica, "sans-serif"',
fontSize: 14,
align: 'center',
listening: true
});
var textNode16 = new Konva.Text({
text: 'X',
x: 175, // France
y: 290,
width: 100,
height: 15,
fontFamily: 'Arial, Helvetica, "sans-serif"',
fontSize: 14,
align: 'center',
listening: true
});
text_overlay.add(textNode0);
text_overlay.add(textNode15);
text_overlay.add(textNode16);
text_overlay.draw();
console.log(text_overlay.getZIndex());
textNode0.on('click', () => {
// create textarea over canvas with absolute position
// first we need to find its position
var textPosition = textNode0.getAbsolutePosition();
var stageBox = stage.getContainer().getBoundingClientRect();
var areaPosition = {
x: textPosition.x + stageBox.left,
y: textPosition.y + stageBox.top
};
// create textarea and style it
var textarea = document.createElement('textarea');
document.body.appendChild(textarea);
textarea.value = textNode0.text();
textarea.style.textAlign = 'center';
textarea.style.resize = 'none';
textarea.style.position = 'absolute';
textarea.style.left = areaPosition.x + 'px'; //positioning needs work
textarea.style.top = areaPosition.y + 'px';
textarea.style.width = textNode0.width();
textarea.style.background = 'transparent';
textarea.style.border = 1; // final border = 0
textarea.style.outline = 'none';
textarea.style.fontFamily = 'Arial, Helvetica, "sans-serif"';
textarea.style.fontSize = 14;
textarea.focus();
textarea.addEventListener('keydown', function (e) {
// hide on enter
if (e.keyCode === 13) {
textNode0.text(textarea.value);
text_overlay.draw();
document.body.removeChild(textarea);
}
});
})
textNode15.on('click', () => {
// create textarea over canvas with absolute position
// first we need to find its position
var textPosition = textNode15.getAbsolutePosition();
var stageBox = stage.getContainer().getBoundingClientRect();
var areaPosition = {
x: textPosition.x + stageBox.left,
y: textPosition.y + stageBox.top
};
// create textarea and style it
var textarea = document.createElement('textarea');
document.body.appendChild(textarea);
textarea.value = textNode15.text();
textarea.style.textAlign = 'center';
textarea.style.resize = 'none';
textarea.style.position = 'absolute';
textarea.style.left = areaPosition.x - 20 + 'px'; //positioning needs work
textarea.style.top = areaPosition.y - 20 + 'px';
textarea.style.width = textNode15.width();
textarea.style.background = 'transparent';
textarea.style.border = 1; // final border = 0
textarea.style.outline = 'none';
textarea.style.fontFamily = 'Arial, Helvetica, "sans-serif"';
textarea.style.fontSize = 14;
textarea.focus();
textarea.addEventListener('keydown', function (e) {
// hide on enter
if (e.keyCode === 13) {
textNode15.text(textarea.value);
text_overlay.draw();
document.body.removeChild(textarea);
}
});
})
textNode16.on('click', () => {
// create textarea over canvas with absolute position
// first we need to find its position
var textPosition = textNode16.getAbsolutePosition();
var stageBox = stage.getContainer().getBoundingClientRect();
var areaPosition = {
x: textPosition.x + stageBox.left,
y: textPosition.y + stageBox.top
};
// create textarea and style it
var textarea = document.createElement('textarea');
document.body.appendChild(textarea);
textarea.value = textNode16.text();
textarea.style.textAlign = 'center';
textarea.style.resize = 'none';
textarea.style.position = 'absolute';
textarea.style.left = areaPosition.x - 45 + 'px'; //positioning needs work
textarea.style.top = areaPosition.y - 20 + 'px';
textarea.style.width = textNode16.width();
textarea.style.background = 'transparent';
textarea.style.border = 1; // final border = 0
textarea.style.outline = 'none';
textarea.style.fontFamily = 'Arial, Helvetica, "sans-serif"';
textarea.style.fontSize = 14;
textarea.focus();
textarea.addEventListener('keydown', function (e) {
// hide on enter
if (e.keyCode === 13) {
textNode16.text(textarea.value);
text_overlay.draw();
document.body.removeChild(textarea);
}
});
})
// add the layer to the stage
stage.add(text_overlay);
根据实验,layer.listening() 设置监听图层而不是其内容。它不直观,但它是有道理的,因为一个层实际上是一个 HTML5 canvas。例如,您可能想要在层背景上切换鼠标移动跟踪,但层 child 形状仍然连续监听,所以您需要这个。
您可以使用 getchildren function
在 children 上设置监听
// get all children
var children = layer.getChildren();
然后迭代列表并对每个成员使用 setListening()。 getChildren() 函数可以与 className 过滤器结合使用以创建 child objects 的子集,因此您可以切换所有文本元素、所有多边形或所有圆等。这很时髦。
作为旁注,不要将此视为批评,您的编码风格似乎不是 DRY. What I mean is, your click events for the textNode0, textNode15 and textNode16 are repetitive - I guess each time you realise you need to make a change to one you have to make it manually to all. That leaves you open to bugs by cut & paste or omission. Better to make a standard myTextNode object and have it include all the functionality that you want in a textNode, then pass in the unique parameters when you create each object. That way making a change to the myTextNode 'class' affects all of them at once. The label for this is 'JS Objects', but if you Google that you will be overloaded with information. Have a read of this at W3 Schools 对于 'way in' 主题。如果您知道所有这些,请原谅我,但是您的文本节点有很多国家/地区。
在 KonvaJS 中,是否可以在单击按钮时使层处于非活动状态(但不是不可见),然后在单击另一个按钮时处于活动状态?我已经尝试 "text_overlay.listening(false);" 但它不起作用。我可以使用 "textNode0.listening(false);" 停用单个文本节点,这确实会阻止用户编辑该文本,但这些文本节点位于多边形上,其中一些非常小(例如,欧洲地图上的卢森堡)并且文本区域会阻止用户单击下面的多边形(例如,更改其填充颜色)。此外,将有超过 40 个文本节点需要处理,因此停用 1 层是更可取的!
这是 HTML 文件的按钮部分:
<script src="js/text-input21.js"></script>
<!-- button events -->
<script>
// button states on load
var btnLabelClicked = true;
var btnColorClicked = false;
var btnDrawLinesClicked = false;
//color chip buttons
var btnViolet = document.getElementById("fillViolet");
var btnOrange = document.getElementById("fillOrange");
var btnYellow = document.getElementById("fillYellow");
//color chip buttons' fill when btnLabelClicked = true
btnViolet.style.background = disableBtnFill;
btnOrange.style.background = disableBtnFill;
btnYellow.style.background = disableBtnFill;
var buttonID = 'btnLabel';
function replyClick(clickedID) {
buttonID = (clickedID);
if (buttonID === 'btnColor') {
textNode0.listening(false);
textNode15.listening(false);
textNode16.listening(false);
btnViolet.disabled = false;
btnViolet.style.background = '#842dce';
btnOrange.disabled = false;
btnOrange.style.background = '#ffa500';
btnYellow.disabled = false;
btnYellow.style.background = '#ffff00';
btnLabelClicked = false;
btnColorClicked = true;
btnDrawLinesClicked = false;
} else if (btnColorClicked && (buttonID === 'fillViolet' || buttonID === 'fillOrange' || buttonID === 'fillYellow')) {
//text_overlay.listening(false);
textNode0.listening(false);
textNode15.listening(false);
textNode16.listening(false);
newFill = document.getElementById(buttonID).style.background;
} else if (buttonID === 'btnLabel' || buttonID === 'btnDrawLines' || buttonID === 'btnEraseLines' || buttonID === 'btnExport') {
//disable color buttons
btnColorClicked = false;
btnViolet.disabled = true;
btnViolet.style.background = disableBtnFill;
btnOrange.disabled = true;
btnOrange.style.background = disableBtnFill;
btnYellow.disabled = true;
btnYellow.style.background = disableBtnFill;
if (buttonID === 'btnLabel') {
textNode0.listening(true);
textNode15.listening(true);
textNode16.listening(true);
btnLabelClicked = true;
btnDrawLinesClicked = false;
} else { //buttonID is not btnLabel or any of the color buttons
textNode0.listening(false);
textNode15.listening(false);
textNode16.listening(false);
btnLabelClicked = false;
btnDrawLinesClicked = true;
}
}
}
</script>
这是包含 text_overlay 层的文本-input21.js 文件:
var text_overlay = new Konva.Layer({
listening: true
});
stage.add(text_overlay);
var textNode0 = new Konva.Text({
text: 'X',
x: 80, // centered between Ireland & Great Britain
y: 125,
width: 150,
height: 15,
fontFamily: 'Arial, Helvetica, "sans-serif"',
fontSize: 14,
align: 'center',
listening: true
});
var textNode15 = new Konva.Text({
text: 'X',
x: 230, // Luxembourg
y: 225,
width: 100,
height: 15,
fontFamily: 'Arial, Helvetica, "sans-serif"',
fontSize: 14,
align: 'center',
listening: true
});
var textNode16 = new Konva.Text({
text: 'X',
x: 175, // France
y: 290,
width: 100,
height: 15,
fontFamily: 'Arial, Helvetica, "sans-serif"',
fontSize: 14,
align: 'center',
listening: true
});
text_overlay.add(textNode0);
text_overlay.add(textNode15);
text_overlay.add(textNode16);
text_overlay.draw();
console.log(text_overlay.getZIndex());
textNode0.on('click', () => {
// create textarea over canvas with absolute position
// first we need to find its position
var textPosition = textNode0.getAbsolutePosition();
var stageBox = stage.getContainer().getBoundingClientRect();
var areaPosition = {
x: textPosition.x + stageBox.left,
y: textPosition.y + stageBox.top
};
// create textarea and style it
var textarea = document.createElement('textarea');
document.body.appendChild(textarea);
textarea.value = textNode0.text();
textarea.style.textAlign = 'center';
textarea.style.resize = 'none';
textarea.style.position = 'absolute';
textarea.style.left = areaPosition.x + 'px'; //positioning needs work
textarea.style.top = areaPosition.y + 'px';
textarea.style.width = textNode0.width();
textarea.style.background = 'transparent';
textarea.style.border = 1; // final border = 0
textarea.style.outline = 'none';
textarea.style.fontFamily = 'Arial, Helvetica, "sans-serif"';
textarea.style.fontSize = 14;
textarea.focus();
textarea.addEventListener('keydown', function (e) {
// hide on enter
if (e.keyCode === 13) {
textNode0.text(textarea.value);
text_overlay.draw();
document.body.removeChild(textarea);
}
});
})
textNode15.on('click', () => {
// create textarea over canvas with absolute position
// first we need to find its position
var textPosition = textNode15.getAbsolutePosition();
var stageBox = stage.getContainer().getBoundingClientRect();
var areaPosition = {
x: textPosition.x + stageBox.left,
y: textPosition.y + stageBox.top
};
// create textarea and style it
var textarea = document.createElement('textarea');
document.body.appendChild(textarea);
textarea.value = textNode15.text();
textarea.style.textAlign = 'center';
textarea.style.resize = 'none';
textarea.style.position = 'absolute';
textarea.style.left = areaPosition.x - 20 + 'px'; //positioning needs work
textarea.style.top = areaPosition.y - 20 + 'px';
textarea.style.width = textNode15.width();
textarea.style.background = 'transparent';
textarea.style.border = 1; // final border = 0
textarea.style.outline = 'none';
textarea.style.fontFamily = 'Arial, Helvetica, "sans-serif"';
textarea.style.fontSize = 14;
textarea.focus();
textarea.addEventListener('keydown', function (e) {
// hide on enter
if (e.keyCode === 13) {
textNode15.text(textarea.value);
text_overlay.draw();
document.body.removeChild(textarea);
}
});
})
textNode16.on('click', () => {
// create textarea over canvas with absolute position
// first we need to find its position
var textPosition = textNode16.getAbsolutePosition();
var stageBox = stage.getContainer().getBoundingClientRect();
var areaPosition = {
x: textPosition.x + stageBox.left,
y: textPosition.y + stageBox.top
};
// create textarea and style it
var textarea = document.createElement('textarea');
document.body.appendChild(textarea);
textarea.value = textNode16.text();
textarea.style.textAlign = 'center';
textarea.style.resize = 'none';
textarea.style.position = 'absolute';
textarea.style.left = areaPosition.x - 45 + 'px'; //positioning needs work
textarea.style.top = areaPosition.y - 20 + 'px';
textarea.style.width = textNode16.width();
textarea.style.background = 'transparent';
textarea.style.border = 1; // final border = 0
textarea.style.outline = 'none';
textarea.style.fontFamily = 'Arial, Helvetica, "sans-serif"';
textarea.style.fontSize = 14;
textarea.focus();
textarea.addEventListener('keydown', function (e) {
// hide on enter
if (e.keyCode === 13) {
textNode16.text(textarea.value);
text_overlay.draw();
document.body.removeChild(textarea);
}
});
})
// add the layer to the stage
stage.add(text_overlay);
根据实验,layer.listening() 设置监听图层而不是其内容。它不直观,但它是有道理的,因为一个层实际上是一个 HTML5 canvas。例如,您可能想要在层背景上切换鼠标移动跟踪,但层 child 形状仍然连续监听,所以您需要这个。
您可以使用 getchildren function
在 children 上设置监听// get all children
var children = layer.getChildren();
然后迭代列表并对每个成员使用 setListening()。 getChildren() 函数可以与 className 过滤器结合使用以创建 child objects 的子集,因此您可以切换所有文本元素、所有多边形或所有圆等。这很时髦。
作为旁注,不要将此视为批评,您的编码风格似乎不是 DRY. What I mean is, your click events for the textNode0, textNode15 and textNode16 are repetitive - I guess each time you realise you need to make a change to one you have to make it manually to all. That leaves you open to bugs by cut & paste or omission. Better to make a standard myTextNode object and have it include all the functionality that you want in a textNode, then pass in the unique parameters when you create each object. That way making a change to the myTextNode 'class' affects all of them at once. The label for this is 'JS Objects', but if you Google that you will be overloaded with information. Have a read of this at W3 Schools 对于 'way in' 主题。如果您知道所有这些,请原谅我,但是您的文本节点有很多国家/地区。