Как инициировать прослушивание событий для фигур на слое при нажатии кнопки?

Можно ли в 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-input21.js, содержащий слой text_overlay:

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);

person las794    schedule 06.04.2018    source источник


Ответы (1)


Исходя из эксперимента, layer.listening () устанавливает прослушивание слоя, но не его содержимого. Это не интуитивно понятно, но имеет смысл, потому что слой на самом деле является холстом HTML5. Например, вы можете переключить отслеживание движения мыши над фоном слоя, но при этом дочерние фигуры слоев все еще будут прослушивать непрерывно, так что вам это понадобится.

Вы можете настроить прослушивание детей с помощью функции getchildren.

// get all children
var children = layer.getChildren();

Затем выполните итерацию по списку и используйте setListening () для каждого члена. Функцию getChildren () можно комбинировать с фильтром className для создания подмножеств дочерних объектов, чтобы вы могли переключать все текстовые элементы, или все многоугольники, или все круги и т. Д. Это довольно забавно.

В качестве примечания и не воспринимайте это как критику, ваш стиль кодирования не кажется СУХИМ. Я имею в виду, что ваши события щелчка для textNode0, textNode15 и textNode16 повторяются - я думаю, каждый раз, когда вы понимаете, что вам нужно внести изменения в один, вы должны делать это вручную для всех. Это оставляет вас уязвимым для ошибок путем вырезания и вставки или пропусков. Лучше создать стандартный объект myTextNode и включить в него все функции, которые вы хотите использовать в textNode, а затем передавать уникальные параметры при создании каждого объекта. Таким образом, внесение изменений в «класс» myTextNode влияет на всех сразу. Ярлык для этого - «Объекты JS», но если вы погуглите, вы будете перегружены информацией. Прочтите это в школах W3, чтобы получить «вводный курс» по предмету. Простите, если вы все это знаете, но для ваших текстовых узлов много стран.

person Vanquished Wombat    schedule 07.04.2018
comment
Большое спасибо! Представьте, как я впитываю информацию, как губка - я новичок в этом, я никогда не слышал отсылки к DRY vs WET (слишком забавно, кстати). Я включу ваше предложение getChildren напрямую, а затем сбегу, чтобы правильно изучить объекты. У меня тоже есть почти 40 форм - вариации на одну и ту же тему - и я пытался найти способ использовать массивы, чтобы избежать повторения, но это не сработало (опять же, я новичок). Спасибо за направление! - person las794; 07.04.2018
comment
Что касается объектов, в первую очередь вам нужно знать, как использовать new с функцией для создания объекта, а затем как использовать this внутри объекта. Я рекомендую вам также найти, как передать объект в качестве параметра - таким образом вы можете создавать свои текстовые объекты как var textDef1={x: 10, y: 20, width: 100, height: 80, text: 'x'....), что делает `` тупой '' объект без методов, а затем передавать это в свою функцию myTextObject через var TextObject1 = new myTextObjectClass(textDef1), что дает вам возможность добавить методы и т. д. Метод - это функция внутри myTextObject. - person Vanquished Wombat; 08.04.2018