我想獲取某些給定坐標的 SVG 元素。
我嘗試使用document.elementsFromPoint(x,y). 但是,它只回傳主svg元素本身,而不回傳svg 中的子元素(圓圈、路徑等)。
=>如何找到給定坐標的 SVG 元素?
我想通過按箭頭鍵在綠色路徑上移動紅色圓圈的示例 html 檔案。只有當圓圈保持在綠色路徑上時,才應允許移動。
截屏:

演示:
<html>
<head>
<script src="https://d3js.org/d3.v7.min.js"></script>
</head>
<body>
<script>
function onClick() {
alert('You have clicked the circle.')
}
function onKeyPress(event) {
switch (event.keyCode) {
case 37:
moveLeft();
break;
case 38:
moveUp();
break;
case 39:
moveRight();
break;
case 40:
moveDown();
break;
default:
}
}
function moveDown() {
console.log('down');
var path = d3.select('#path');
var robot = d3.select('#robot');
var cx = Number(robot.attr('cx'));
var cy = Number(robot.attr('cy'));
var newcy = cy 10;
var elements = document.elementsFromPoint(cx, newcy)
if (path in elements) {
robot.attr('cy', cy 10);
}
}
function moveUp() {
console.log('up');
var robot = d3.select('#robot');
var cy = Number(robot.attr('cy'));
robot.attr('cy', cy - 10);
}
function moveLeft() {
console.log('left')
var robot = d3.select('#robot');
var cx = Number(robot.attr('cx'));
robot.attr('cx', cx - 10);
}
function moveRight() {
console.log('right');
var robot = d3.select('#robot');
var cx = Number(robot.attr('cx'));
robot.attr('cx', cx 10);
}
function onLoad() {
console.log('onload')
this.addEventListener('keydown', event => onKeyPress(event));
}
</script>
<svg width='500px' height='500px' focusable onload="onLoad()">
<text x='0' y='20' fill='blue'>Hello world from within svg! Press arrow keys to move the circle:</text>
<path id="path" d="M100 100 L 100 200 L 200 200" stroke='green' fill="transparent"/>
<circle id="robot" cx="100" cy="100" r="5" fill='red' onclick="onClick()" />
</svg>
</body>
</html>
uj5u.com熱心網友回復:
因為Document.elementsFromPoint()與視口相關,所以您可以使用Element.getBoundingClientRect()也與視口相關。因此,機器人位置(中心)是 x/y 位置加上寬度/高度的一半的結果。在找到元素陣列后,您可以測驗是否indexOf()大于 -1。
svg {
margin: 15px;
}
<html>
<body>
<script>
var step = 10;
function onLoad(){
console.log('onload')
disableKeyboardScrolling();
this.addEventListener('keydown', event => onKeyPress(event));
}
function disableKeyboardScrolling(){
window.addEventListener("keydown", function(e) {
if(["ArrowUp","ArrowDown","ArrowLeft","ArrowRight"].indexOf(e.code) > -1) {
e.preventDefault();
}
}, false);
}
function onClick(){
alert('You have clicked the circle.')
}
function onKeyPress(event){
switch(event.code){
case "ArrowLeft": moveLeft();
break;
case "ArrowUp": moveUp();
break;
case "ArrowRight": moveRight();
break;
case "ArrowDown": moveDown();
break;
default:
}
}
function moveDown(){
console.log('down');
var robot = document.getElementById('robot');
var coordinates = getCenterCoordinates(robot);
var newx = coordinates[0];
var newy = coordinates[1] step;
if (isOnAllowedPath(newx, newy)) {
let cy = Number(robot.getAttribute('cy'))
let newCy = cy step;
robot.setAttribute('cy', newCy);
}
}
function moveUp(){
console.log('up');
var robot = document.getElementById('robot');
var coordinates = getCenterCoordinates(robot);
var newx = coordinates[0];
var newy = coordinates[1] - step;
if (isOnAllowedPath(newx, newy)) {
let cy = Number(robot.getAttribute('cy'))
let newCy = cy-step;
robot.setAttribute('cy', newCy);
}
}
function moveLeft(){
console.log('left')
var robot = document.getElementById('robot');
var coordinates = getCenterCoordinates(robot);
var newx = coordinates[0] -step;
var newy = coordinates[1];
if (isOnAllowedPath(newx, newy)) {
let cx = Number(robot.getAttribute('cx'))
let newCx = cx-step;
robot.setAttribute('cx', newCx);
}
}
function moveRight(){
console.log('right');
var robot = document.getElementById('robot');
var coordinates = getCenterCoordinates(robot);
var newx = coordinates[0] step;
var newy = coordinates[1];
if (isOnAllowedPath(newx, newy)) {
let cx = Number(robot.getAttribute('cx'))
let newCx = cx step;
robot.setAttribute('cx', newCx);
}
}
function getCenterCoordinates(robot){
let rect = robot.getBoundingClientRect();
let x = rect.x rect.width / 2;
let y = rect.y rect.height / 2;
return [x, y]
}
function isOnAllowedPath(x,y){
var allowedPaths = document.getElementsByClassName('allowed-path');
var elementsAtPosition = document.elementsFromPoint(x,y);
for(allowedPath of allowedPaths){
let isAllowed = elementsAtPosition.indexOf(allowedPath) > -1;
if (isAllowed){
return true;
}
}
return false;
}
</script>
<svg
width='500px'
height='500px'
focusable
onload="onLoad()"
>
<text x='0' y='20' fill='blue'>Hello world from within svg! Please move the circle with arrow keys:</text>
<path class="allowed-path" d="M100 100 L 100 200 L 200 200" stroke='green' fill="transparent"/>
<path class="allowed-path" d="M200 200 L 200 100 L 300 100" stroke='blue' fill="transparent"/>
<circle id="robot" cx="100" cy="100" r="5" fill='red' onclick="onClick()" />
</svg>
</body>
</html>
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/312451.html
標籤:javascript svg
