Chrome не запускает событие щелчка для элемента SVG (Firefox делает)
Я наблюдаю несоответствие / ошибку при обработке события нажатия в различных браузерах (Chrome, Edge, Firefox).
В моей библиотеке JavaScript, которая использует SVG, я создаю перетаскиваемые и перетаскиваемые прямоугольники. Когда я запускаю свой фрагмент в браузере Chrome, событие click не срабатывает, если на холсте присутствуют 2 или более элементов.
Чтобы проверить это, вам нужно создать как минимум 2 прямоугольника на холсте. Вы можете перетащить их мышью (начальная позиция прямоугольников остается прежней). Обычно граница прямоугольника становится коричневой, если событие срабатывает по элементу.
Странно то, что Firefox запускает событиенажатия, как и ожидалось, но Chrome вообще не запускает событие. Браузер MS Edge запускает событие щелчка по двойному щелчку.
PS: код представлен здесь в полном объеме, так что вы можете запустить пример:
"use strict";
var SVGCanvas = undefined;
var canvClientRect = {};
function initScript() {
SVGCanvas = document.getElementById("playSVGCanvas");
canvClientRect.width = SVGCanvas.getClientRects()[0].width;
canvClientRect.height = SVGCanvas.getClientRects()[0].height;
}
function createRect() {
var newRect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
var rectX0 = 20;
var rectY0 = 20;
var rectWidth = 100;
var rectHeight = 50;
newRect.setAttributeNS(null, "x", rectX0);
newRect.setAttributeNS(null, "y", rectY0);
newRect.setAttributeNS(null, "width", rectWidth);
newRect.setAttributeNS(null, "height", rectHeight);
newRect.setAttributeNS(null, "class", "draggable rect inactive");
newRect.setAttributeNS(null, "onmousedown", "selectElement(evt)");
newRect.setAttributeNS(null, "onclick", "clickHandler(evt)");
SVGCanvas.appendChild(newRect);
}
var currentX = 0;
var currentY = 0;
var shapeWidth = undefined;
var shapeHeight = undefined;
var wasMoved = false;
function selectElement(evt) {
evt.preventDefault();
var targetEl = evt.target;
currentX = evt.clientX;
currentY = evt.clientY;
shapeWidth = targetEl.getAttributeNS(null, "width");
shapeHeight = targetEl.getAttributeNS(null, "height");
if (SVGCanvas.childElementCount >= 2) {
// change element's order to show selected item on the top
SVGCanvas.appendChild(targetEl);
}
targetEl.setAttributeNS(null, "onmousemove", "moveElement(evt)");
targetEl.setAttributeNS(null, "onmouseout", "deselectElement(evt)");
targetEl.setAttributeNS(null, "onmouseup", "deselectElement(evt)");
wasMoved = false;
}
function moveElement(evt) {
evt.preventDefault();
var targetEl = evt.target;
var dx = evt.clientX - currentX;
var dy = evt.clientY - currentY;
currentX = evt.clientX;
currentY = evt.clientY;
var newX = parseInt(targetEl.getAttributeNS(null, "x")) + dx;
var newY = parseInt(targetEl.getAttributeNS(null, "y")) + dy;
if(newX < 0) {
targetEl.setAttributeNS(null, "x", 0);
} else if (newX > canvClientRect.width - shapeWidth) {
targetEl.setAttributeNS(null, "x", canvClientRect.width - shapeWidth);
} else {
targetEl.setAttributeNS(null, "x", newX);
}
if (newY < 0) {
targetEl.setAttributeNS(null, "y", 0);
} else if (newY > canvClientRect.height - shapeHeight) {
targetEl.setAttributeNS(null, "y", canvClientRect.height - shapeHeight);
} else {
targetEl.setAttributeNS(null, "y", newY);
}
wasMoved = true;
}
function deselectElement(evt) {
if (evt == null) {
console.log("Event == null");
return;
}
evt.target.removeAttributeNS(null, "onmousemove");
evt.target.removeAttributeNS(null, "onmouseout");
evt.target.removeAttributeNS(null, "onmouseup");
}
function clickHandler(evt) {
// click event fires even element was moved
// we don't handle click if element was moved
if (wasMoved) { return; }
var targetEl = evt.target;
if (targetEl.classList.contains("active")) {
deActivateElm(targetEl);
} else {
activateElm(targetEl);
}
}
function activateElm(elm) {
elm.classList.remove("inactive");
elm.classList.add("active");
}
function deActivateElm(elm) {
elm.classList.remove("active");
elm.classList.add("inactive");
}
#workCanv {
width: 100%;
height: 180px;
border: 1px solid black;
}
.draggable {
cursor: move;
}
.rect {
stroke-width: 4;
fill: lightgrey;
}
.active {
stroke: brown
}
.inactive {
stroke: black
}
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="wcstyle.css">
<script src="wccontroller.js"></script>
</head>
<body onload="initScript()">
<div id="panel">
<button type="button" name="addRectagble" onclick="createRect()">Add rectangle</button>
</div>
<div id="workCanv">
<svg xmlns="http://www.w3.org/2000/svg" height="100%" width="100%" id="playSVGCanvas">
</svg>
</div>
</body>
1 ответ
Через некоторое время я сообщил об этом вопросе команде разработчиков Chrome, потому что думал, что это ошибка. Но это не так. Поведение для случаев, когда элемент удаляется из дерева документа и затем добавляется обратно перед наведением мыши (например, appendChild(lastChild)), еще не определено комитетом W3. В результате поведение меняется от браузера к браузеру.
Ход решения проблемы можно отслеживать по следующим ссылкам: