ps0604
ps0604

Reputation: 1071

Position mouse pointer on line/path in Raphael

In this jsFiddle I have a Raphael canvas with a line/path where the user can drag it.

Problem is that the exact top pixel of the mouse pointer has to be on the line to be able to drag it. I need Raphael to be more "forgiving" and let the user drag the line if it touches the top, say, 3 pixels of the pointer.

I added mouseover/mouseout events to actually tell when the mouse is over the line, otherwise is very difficult to know.

So the question is: is there a way to drag the line without having to accurately position the mouse pointer?

var paper = Raphael("canvas", 600, 600); 
var line = this.paper.path('M10 10 L50 50');

var start = function () {
      this.odx = 0;
      this.ody = 0;
},
move = function (dx, dy) {
      this.translate(dx - this.odx, dy - this.ody);
      this.odx = dx;
      this.ody = dy;
},
up = function () {};

line.drag(move, start, up);

line.mouseover(function(e) {
    line.attr('stroke', 'red');
});

line.mouseout(function(e) {
  line.attr('stroke', 'black');
});

Upvotes: 1

Views: 360

Answers (1)

traktor
traktor

Reputation: 19301

The Raphael library creates an SVG element (not a CANVAS element) for drawing purposes, and drawing lines creates PATH elements within the SVG element.

I had some success by increasing the line width on hover. You do have to trigger the width change by at least moving the mouse over the line, but it is a lot easier to select afterwards. While the visual effect produced may not be perfect (some width flicking can occur) continuing the drag operation proceeds without problem.

You could try increasing the line width by either modifying the stroke-width attribute in the mouseover and mouseout handlers:

line.mouseover(function(e) {
    line.attr('stroke', 'red');
    line.attr('stroke-width', '9')
});

line.mouseout(function(e) {
  line.attr('stroke', 'black');
  line.attr('stroke-width', '1')
});

or by modifying the stroke-width styling when hovering over all path elements in CSS using

path:hover {
   stroke-width: 9;
}


According to this question Raphael does not provide an abstraction of all possible CSS styling so it could use VML in XML documents. If you can live without IE 9 support and expect users to have a modern browser you may be interested in the following snippet which

  • increases the width of a line on mouseover by setting class name draggable, which sets a move cursor,
  • when a move is started replaces draggable with dragging ( which removes the width increase) and sets a move cursor over the svg container,
  • removes class draggable, but not dragging, on mouseout
  • cleans up classes and the cursor in the up function.

"use strict";
var container = document.getElementById("canvas");
var paper = Raphael("canvas", 600, 600);
var line = this.paper.path('M10 10 L50 50');
var start = function () {
   this.odx = 0;
   this.ody = 0;
},
move = function (dx, dy) {
    this.translate(dx - this.odx, dy - this.ody);
    this.odx = dx;
    this.ody = dy;
    if( this.node.classList.contains("draggable")) {
        this.node.classList.replace("draggable", "dragging");
        container.classList.add("moveCursor");
    }
}, 
up = function (e) {
    line.node.classList.remove("draggable", "dragging");
    container.classList.remove("moveCursor");
};

line.drag(move, start, up);
line.mouseover(function(e) {
    if(!e.target.classList.contains("dragging")) {
        e.target.setAttribute("class", "draggable");
    }
});
.draggable:hover {
    stroke-width: 9;
    stroke:red;
    cursor: move;
} 
path.dragging {
    stroke: red;
}
.moveCursor{
    cursor:move;
}
svg {
   border: thin solid blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>

<!-- body-html -->
<div id="canvas"></div>

The code is basically for demonstration - if you drag a line outside the SVG element you can't see it or grab it to drag back.

Some CSS rules (i.e. path.dragging) needed additional specificity to take priority over the defaults supplied by Raphael.

Upvotes: 2

Related Questions