Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Raphael - Drawing shapes with mouse

Tags:

raphael

What would be the best way to draw a rectangle or circle for that matter using your mouse ?

I just started looking at raphael and it seems I should use, drag? Or mousedown and mouseup ?

No sure.

like image 506
Harry Avatar asked Oct 05 '11 12:10

Harry


3 Answers

I would use mousedown and mouseup events on your canvas/paper. On mouse down you should store the x and y positions of the mousedown, then on mouseup you should use the current mouse positions to calculate width and height.

Here is an example, bear in mind thought that I am using JQuery to calculate the mouse positions (if this is not available for you, then you should find another way to get the mouse offsets)

//global variables
var mouseDownX = 0;
var mouseDownY = 0;

//register events on document load
paper.mousedown(OnMouseDown);
paper.mouseup(OnMouseUp);

function OnMouseDown(e){
   var offset = $("#Canvas").offset();//This is JQuery function
   mouseDownX = e.pageX - offset.left;
   mouseDownY = e.pageY - offset.top;
}

function OnMouseUp(e){
   var offset = $("#Canvas").offset();//This is JQuery function
   var upX = e.pageX - offset.left;
   var upY = e.pageY - offset.top;

   var width = upX - mouseDownX;
   var height = upY - mouseDownY;

   DrawRectangle(mouseDownX, mouseDownY, width, height);
}

function DrawRectangle(x, y, w, h){
   var element = paper.rect(x, y, w, h);
   element.attr({
            fill: "#FFF",
            stroke: "#F00"
        });
}

Hope that helps

like image 83
musefan Avatar answered Nov 29 '22 10:11

musefan


Here's an updated version of fiddle (mentioned in the other article) that works with Raphael 2+ (no paper events).

This fiddle shows how a rectangle is dynamically drawn while you drag the mouse.

var mouseDownX = 0;
var mouseDownY = 0;
var elemClicked;
var rect;

$(document).ready(function() {
    var paper = Raphael("d1", 300, 200);

    // start, move, and up are the drag functions
    start = function() {
        // storing original coordinates
        this.ox = this.attr("x");
        this.oy = this.attr("y");
        this.attr({
            opacity: 1
        });
        if (this.attr("y") < 60 && this.attr("x") < 60) this.attr({
            fill: "#000"
        });
    }, move = function(dx, dy) {

        // move will be called with dx and dy
        if (this.attr("y") > 200 || this.attr("x") > 300) this.attr({
            x: this.ox + dx,
            y: this.oy + dy
        });
        else {
            nowX = Math.min(300, this.ox + dx);
            nowY = Math.min(200, this.oy + dy);
            nowX = Math.max(0, nowX);
            nowY = Math.max(0, nowY);
            this.attr({
                x: nowX,
                y: nowY
            });
            if (this.attr("fill") != "#000") this.attr({
                fill: "#000"
            });
        }

    }, up = function() {
        // restoring state
        this.attr({
            opacity: .5
        });
        if (this.attr("y") < 60 && this.attr("x") < 60) this.attr({
            fill: "#AEAEAE"
        });
    };

    function DrawRectangle(x, y, w, h) {

        var element = paper.rect(x, y, w, h);
        element.attr({
            fill: "gray",
            opacity: .5,
            stroke: "#F00"
        });
        $(element.node).attr('id', 'rct' + x + y);
        console.log(element.attr('x'));

        element.drag(move, start, up);
        element.click(function(e) {

            elemClicked = $(element.node).attr('id');

        });

        return element;

    }

    $("#bind").click(function(e) {
        $('#d1').unbind('mousedown');
        $('#d1').unbind('mousemove');
        $('#d1').unbind('mouseup');

        $("#d1").mousedown(function(e) {
            // Prevent text edit cursor while dragging in webkit browsers
            e.originalEvent.preventDefault();

            var offset = $("#d1").offset();
            mouseDownX = e.pageX - offset.left;
            mouseDownY = e.pageY - offset.top;

            rect = DrawRectangle(mouseDownX, mouseDownY, 0, 0);

            $("#d1").mousemove(function(e) {
                var offset = $("#d1").offset();
                var upX = e.pageX - offset.left;
                var upY = e.pageY - offset.top;

                var width = upX - mouseDownX;
                var height = upY - mouseDownY;

                rect.attr( { "width": width > 0 ? width : 0,
                             "height": height > 0 ? height : 0 } );

            });

        });

        $("#d1").mouseup(function(e) {
            $('#d1').unbind('mousemove');

            var BBox = rect.getBBox();

            if ( BBox.width == 0 && BBox.height == 0 ) rect.remove();

        });

    });

    $("#unbind").click(function(e) {
        $('#d1').unbind('mouseup');
        $('#d1').unbind('mousemove');
        $('#d1').unbind('mousedown');
    });

    $("#clr").click(function(e) {
        $('#d1').find('rect').each(function(i, obj) {
            $(this).remove();
        });
    });

    $("#del").click(function(e) {
        $('#' + elemClicked).remove();
    });

});

like image 33
Miro Avatar answered Nov 29 '22 09:11

Miro


I have tried to modify the above fiddle from Miro. Please check my updated version here

var canvas = $('#canvas');
var paper = Raphael(canvas.attr('id'), canvas.width(), canvas.height());

var mouseDownX = 0;
var mouseDownY = 0;
var elemClicked;
var shap;
var borderColor = '#093';
var fillColor = '#eee';
var option = 1;
var shapOpacity = .5;
var ShapType = {RECTANGLE: 1, CIRCLE: 2, LINE: 3}
$(document).ready(function() {
   $("#action").change(function() {
        option = $('option:selected', this).val();
    });
	
    $("#start").click(function(e) {
		reset();

        $(canvas).mousedown(function(e) {			            
            e.originalEvent.preventDefault();
            var offset = $(canvas).offset();
            mouseDownX = e.pageX - offset.left;
            mouseDownY = e.pageY - offset.top;
			
			if(option == ShapType.RECTANGLE){
            	shap = drawRectangle(mouseDownX, mouseDownY, 0, 0);
			}
			else if(option == ShapType.CIRCLE){
				shap = drawCircle(mouseDownX, mouseDownY, mouseDownX, mouseDownY);
			}else if(option == ShapType.LINE){
				shap = drawLine(mouseDownX, mouseDownY, mouseDownX, mouseDownY);
			}
			
	 
            $(canvas).mousemove(function(e) {
                var offset = $(canvas).offset();
                var upX = e.pageX - offset.left;
                var upY = e.pageY - offset.top;
    
                var width = upX - mouseDownX;
                var height = upY - mouseDownY;
				
				if(option == ShapType.RECTANGLE){	
                	shap.attr( { "width": width > 0 ? width : 0,
                             "height": height > 0 ? height : 0 } );
				}else if(option == ShapType.CIRCLE || option == ShapType.LINE){					   
							shap.updateEnd(upX, upY);
					}
    
            }); // end mouse down.

        });// end mouse down.

        $(canvas).mouseup(function(e) {
            $(canvas).unbind('mousemove');
			if(option == ShapType.RECTANGLE){
				var BBox = shap.getBBox();
				if ( BBox.width == 0 && BBox.height == 0 ) shap.remove();
			}
        }); // end mouse up.
		
    }); // end document ready.

    $("#done").click(function(e) {
        $(canvas).unbind('mouseup');
        $(canvas).unbind('mousemove');
        $(canvas).unbind('mousedown');
    });

    $("#clear").click(function(e) {
        $(canvas).find('rect, circle, path').each(function(i, obj) {
            $(this).remove();
        });
    });

    $("#deleteshap").click(function(e) {
        $('#' + elemClicked).remove();
    });

 var start = function() {
        this.ox = this.attr("x");
        this.oy = this.attr("y");
        this.attr({
            opacity: shapOpacity
        });
		
		this.ow = this.attr('width');
		this.oh = this.attr('height');
    }
	
	var move = function(dx, dy) {
	
         	nowX = Math.min(paper.width, this.ox + dx);
            nowY = Math.min(paper.height, this.oy + dy);
            nowX = Math.max(0, nowX);
            nowY = Math.max(0, nowY);
            this.attr({
                x: nowX,
                y: nowY
            });
			
            if (this.attr("fill") != fillColor) this.attr({
                fill: fillColor
            });
    }
	
	var up = function() {
        this.attr({
            opacity: shapOpacity
        });
        if (this.attr("y") < 60 && this.attr("x") < 60) this.attr({
            fill: fillColor
        });
    };

var reset = function(){
	    $(canvas).unbind('mousedown');
        $(canvas).unbind('mousemove');
        $(canvas).unbind('mouseup');
	}
	
function drawLine(startX, startY, endX, endY) {
    var start = {
        x: startX,
        y: startY
    };
    var end = {
        x: endX,
        y: endY
    };
    var getPath = function() {
        return "M" + start.x + " " + start.y + " L" + end.x + " " + end.y;
    };
	
    var redraw = function() {
        node.attr("path", getPath());
		node.attr({
			stroke: borderColor
		});
    }

    var node = paper.path(getPath());
	 $(node.node).attr('id', 'shap' + startX + startY);	
	 node.click(function(e) {
			elemClicked = $(node.node).attr('id');
			 });
			 	
    return {
        updateStart: function(x, y) {
            start.x = x;
            start.y = y;
            redraw();
            return this;
        },
        updateEnd: function(x, y) {
            end.x = x;
            end.y = y;
            redraw();
            return this;
        }
    };
};

function drawRectangle(x, y, w, h) {
		var element = paper.rect(x, y, w, h);				
        element.attr({
            fill: fillColor,
            opacity: shapOpacity,
            stroke: borderColor
        });
		
        $(element.node).attr('id', 'shap' + x + y);				
        element.drag(move, start, up);
		element.click(function(e) {
			elemClicked = $(element.node).attr('id');
			 });
        return element;
    }
	
function drawCircle(x1, y1, x2, y2)
{
	var center = {
       x: (x1+x2)/2,
       y: (y1+y2)/2
    };

    var radius = {

        h: Math.sqrt((y2 - y1) * (y2 - y1))/2,
        w: Math.sqrt((x2 - x1) * (x2 - x1))/2

    };
    var getPath = function () {

        return [["M", center.x, center.y], ["m", 0, -radius.h], 
               ["a", radius.w, radius.h, 0, 1, 1, 0, 2 * radius.h],
               ["a", radius.w, radius.h, 0, 1, 1, 0, -2 * radius.h],
               ["z"]];

    };
	    var redraw = function () {

        node.attr("path", getPath());
		 node.attr(
            { fill: fillColor,
            	stroke: borderColor,
            });
    };
	
	 var node = paper.path(getPath());
	 $(node.node).attr('id', 'shap' + x1 + y1);	
	 node.click(function(e) {
			elemClicked = $(node.node).attr('id');
			 });
			 
   dragCircle(node);
	return {
        updateStart: function (x, y) {
            center.x = (x1 + x) / 2;
            center.y = (y1 + y) / 2;
            radius.w = Math.sqrt((x - x1) * (x - x1))/2;
            radius.h = Math.sqrt((y - y1) * (y - y1))/2;
            redraw();
            return this;
        },
        updateEnd: function (x, y) {
            center.x = (x1 + x) / 2;
            center.y = (y1 + y) / 2;
            radius.w = Math.sqrt((x - x1) * (x - x1))/2;
            radius.h = Math.sqrt((y - y1) * (y - y1))/2;
            redraw();
            return this;
        }
	};
	
	} // end circle

dragCircle = function(node) {
	 var me = node,
      lx = 0,
      ly = 0,
      ox = 0,
      oy = 0,
      moveFnc = function(dx, dy) {
          lx = dx + ox;
          ly = dy + oy;
          me.transform('t' + lx + ',' + ly);
      },
      startFun = function() {},
      endFnc = function() {
          ox = lx;
          oy = ly;
      };
  
  node.drag(moveFnc, function() {} , endFnc);
	};


});
#canvas{background-color:#eee; background-size:cover; width:400px; height:300px;}
.controls input{background: #15A3D7;border: #eee 1px solid;border-radius: 3px;padding: 3px 12px;margin: 5px 3px;color: #fff;}
.controls select{padding: 3px;background: #eee;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="controls"> 
<input id="start" value="Start" type="button" />
<input id="done" value="Done" type="button" />
<input id="deleteshap" value="Delete Shap" type="button" />
<input id="clear" value="Clear All" type="button" />
<select id="action">
<option value="1">Rectangle</option>
<option value="2">Circle</option>
<option value="3">Line</option>
</select>
</div>
<div class="dvcls" id="canvas"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.2/raphael-min.js"></script>

Here is also a good reference to play with Raphael Js.

http://www.ebooksbucket.com/instant-raphaeljs-starter-b184

Hope this will help.

like image 39
Rana Imtiaz Avatar answered Nov 29 '22 10:11

Rana Imtiaz