byteC0de
byteC0de

Reputation: 5273

How to move an object in svg path using keyboard

I have an SVG path given below. I need to move that red dot using the keyboard. If a turn coming need to use left or right arrow button based on the turn. How can I achieve this using javascript?

enter image description here

Upvotes: 0

Views: 741

Answers (3)

Stranger in the Q
Stranger in the Q

Reputation: 3898

may be you can use iconic font?

window.focus();
document.addEventListener('keydown', e => {
  let direction = e.keyCode - 38;
  if (Math.abs(direction) !== 1) return;
  let offset = parseFloat(player.getAttribute('startOffset'));
  offset = (offset + direction + 98)%98;
  player.setAttribute('startOffset', offset + '%');
})
<svg viewbox=0,0,300,200 width=90vw height=90vh>
    <path id="route" stroke="red" fill="none" d="M75,120L100,0l100,30q110,100,10,150z"/>
    <text><textPath xlink:href="#route" id="player" startOffset="0%">🚗</textPath></text>  
</svg>

Upvotes: 1

ccprog
ccprog

Reputation: 21856

Here is a function that catches arrow keystrokes. The difference to enxaneta's solution is

  • the use of event.key instead of event.keyCode, which is deprecated. Internet Explorer and Edge < v17 unfortunately use different identifier strings. A complete description of the current state of affairs is here. If you really want to stay with keyCode, see here for compatibility lists.
  • if an action is associated with a key, event.preventDefault() is set. Otherwise the window might scroll. It is not used globally, as that would block all keyboard interactions with the window.

    document.addEventListener('keydown', function (event) {
        switch (event.key) {
        case 'Left':
        case 'ArrowLeft':
            // game action
            return event.preventDefault();
        case 'Up':
        case 'ArrowUp':
            // game action
            return event.preventDefault();
        case 'Right':
        case 'ArrowRight':
            // game action
            return event.preventDefault();
        case 'Down':
        case 'ArrowDown':
            // game action
            return event.preventDefault();
        }
    });
    

Upvotes: 0

enxaneta
enxaneta

Reputation: 33054

I don't think you can use left or right arrow to move the red dot the way you intend. In fact I don't understand the logic. Please define right and left tun.

However you can move the dot forwards or backwards by using the right and left arrow.

In my code the starting value is 0 and the red dot is at the beginning of the path. The value increases or decreases depending on the arrow key you use.

The step is 1/100 of the path's length.

if(e.keyCode == 37){value ++;}
else if(e.keyCode == 39){value --;}

If the value is less than 0 or bigger than 100 I reset the value:

if(value > 100){value %= 100;}
if(value < 0){value += 100}

I get the position on the path using the getPointAtLength() method. I hope this is what you need.

let position = circuit.getPointAtLength(totalLength*value/100);

let totalLength = circuit.getTotalLength();


let value = 0;

window.addEventListener("keydown",(e)=>{
  
  if(e.keyCode == 37){value ++;}
  else if(e.keyCode == 39){value --;}
  
  if(value > 100){value %= 100;}
  if(value < 0){value += 100}
  
  let position = circuit.getPointAtLength(totalLength*value/100);
   updateElement({cx:position.x, cy:position.y}, thumb)
  
})



function updateElement(o, element) {
  for (var name in o) {
    if (o.hasOwnProperty(name)) {
      element.setAttributeNS(null, name, o[name]);
    }
  }
  return element;
}
svg{border:1px solid #d9d9d9; max-width:100vh}


#circuit{
  stroke:black;
  fill:none;
  stroke-width: 5px;
  stroke-linejoin:round;
  stroke-linecap:round;
  fill-opacity:.85
}

circle{fill:red}
<svg id="svg" viewBox="30 30 300 300">

	<path id="circuit" d="M187.476,214.443c-2.566,11.574-4.541,22.658-7.542,33.456
		c-3.558,12.8-7.14,25.713-12.242,37.938c-10.223,24.495-41.321,29.239-58.824,9.548c-9.592-10.792-11.295-26.9-3.539-40.556
		c11.233-19.778,25.391-37.46,40.447-54.438c1.07-1.207,2.116-2.436,3.893-4.484c-7.212,0.9-13.349,1.988-19.529,2.374
		c-16.283,1.018-32.578,2.21-48.881,2.437c-18.686,0.261-32.846-10.154-37.071-26.055c-6.762-25.449,15.666-48.973,41.418-43.338
		c23.645,5.175,46.447,12.901,68.424,23.051c1.033,0.478,2.083,0.918,3.933,1.731c-0.83-1.947-1.341-3.225-1.911-4.475
		c-9.896-21.701-18.159-43.986-23.192-67.337c-4.587-21.28,8.933-40.56,29.946-43.257c20.134-2.585,38.124,12.991,39.091,34.294
		c1.029,22.682-0.049,45.292-3.58,67.755c-0.17,1.079-0.152,2.188-0.246,3.659c8.05-6.831,15.471-13.737,23.52-19.811
		c11.147-8.412,22.398-16.795,34.27-24.113c18.35-11.312,40.821-4.481,50.028,14.385c9.091,18.628,0.131,40.586-20.065,48.198
		c-11.034,4.158-22.248,7.944-33.594,11.143c-11.321,3.191-22.908,5.438-34.866,8.212c1.189,0.81,2.19,1.504,3.205,2.18
		c18.402,12.261,37.157,24.032,55.101,36.932c14.769,10.616,18.619,29.317,10.675,44.578c-7.537,14.477-25.151,22.136-40.767,17.583
		c-7.583-2.212-14.022-6.469-18.523-12.919c-12.463-17.86-24.638-35.924-36.898-53.925
		C189.24,217.849,188.547,216.357,187.476,214.443z"/>

  
  <circle id="thumb" cx="187.476" cy="214.443" r="5" fill="black" />
  
 
</svg>

Please do not forget to click the iframe before using the keys.

Upvotes: 3

Related Questions