James Newton
James Newton

Reputation: 7082

<svg> element fails to move when its position is updated during a mouse event

Setting the left and top attributes of an svg element, or a div containing an svg element fails when the call comes from inside a mouse event.

I have created a jsFiddle to illustrate this. Demo HTML page below for reference. Tested in Chrome, Firefox and Safari.

Is this the expected behaviour of svg elements?

I want to the user to be able to drag the svg elements around. How can I achieve this?


<!DOCTYPE html>
<html>
<head>
  <title>SVG</title>
  <meta charset="utf-8" />
  <style>
  .dot {
      position: absolute;
  }

  #green{
      left: 20px;
      top: 20px;
  }

  #orange{
      left: 20px;
      top: 60px;
  }

  #red {
      left: 20px;
      top: 100px;
      background: red;
      height: 20px;
      width: 20px;
  }
  </style>

  <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script> 
</head>

<body>    
    <svg version="1.1"
             xmlns="http://www.w3.org/2000/svg"
             baseProfile="tiny"
             id="green"
             class="dot"
             width="20" height="20">
     <circle cx="10" cy="10" r="10" fill="green" />
    </svg>

    <div id="orange" class="dot">
        <svg version="1.1" xmlns="http://www.w3.org/2000/svg" baseProfile="tiny" width="20" height="20">
            <circle cx="10" cy="10" r="10" fill="orange" />
        </svg>
    </div>

    <div id="red" class="dot"></div>

    <script>
        $(function ready() {
            var dots = $(".dot")
            dots.on("mousedown touchstart", startDrag)

            var $doc
            var $dot
            var offsetX
            var offsetY

            function startDrag(event) {
                $doc = $(document)
                $doc.on("mousemove", drag)
                $doc.on("mouseup", stopDrag)
                $dot = $(event.target)
                var offset = $dot.offset()
                offsetX = offset.left - event.pageX
                offsetY = offset.top - event.pageY
            }

            function stopDrag(event) {
                $doc.off("mousemove mouseup")
            }


            function drag(event) {
                var left = event.pageX + offsetX
                var top = event.pageY + offsetY
                $dot.css({
                    left: left,
                    top: top
                })
            }
        })
    </script>

</body>
</html>

Upvotes: 4

Views: 670

Answers (1)

Fabr&#237;cio Matt&#233;
Fabr&#237;cio Matt&#233;

Reputation: 70139

You want this instead of event.target:

$dot = $(this)

Fiddle

event.target references the DOM element that initiated the event, in your case the <circle> inside the SVG.

In the other hand, this inside a jQuery event handler references the DOM element where the handler has been attached, that is, the .dot element where the event has fired.

Upvotes: 4

Related Questions