Scribbles – Playing with SVG & Greasemonkey
by Zander Kidd
Keith Wood has an excellent jQuery plugin for interacting with an SVG canvas which can be found here. I’m using it in a research project I’m working on currently and will talk about in a later post.
For now though the fact that my project involves Greasemonkey, tracking the mouse cursor, and dynamically displaying visual feedback has led to a nice unintended combination of being able to draw all over webpages with the cursor
1. Load jQuery and SVG
The first thing you’ll need is to make Greasemonkey load jQuery. Now the usual way to do this on your own webpage would be to include <script style="text/javascript" src="<url to jquery.js file>" />. This is the same way you’ll be loading the script with Greasemonkey, essentially you make Greasemonkey add a script line to the pages header.
var GM_JQ = document.createElement('script');
GM_JQ.src = 'http://jquery.com/src/jquery-latest.js';
GM_JQ.type = 'text/javascript';
document.getElementsByTagName('head')[0].appendChild(GM_JQ);
2. Wait for it to load
Your going to be loading jQuery and SVG from a different server and it may be quick anyway but it won’t be instantaneous so you don’t want to try and run the rest of the jQuery dependent part of the script until jQuery has fully loaded.
function loading() {
if(typeof unsafeWindow.jQuery == 'undefined'
|| unsafeWindow.jQuery.svg == 'undefined') {
window.setTimeout(loading,100);
} else {
$ = unsafeWindow.jQuery; startPlugin();
}
}
loading();
This will loop and wait until the jQuery variable isn’t undefined anymore (ie. it’s loaded), and then afterwords assign it to ‘$’ just like you’re used to, and start the drawing goodness.
3. Activate SVG and listen for mouse events
Ok, everythings almost ready to run. Next your going to need a transparent div covering the entire webpage that the SVG canvas can then attach to and draw on.
$("body").prepend("<div id='svg' style='z-index: 999;
position: absolute; width:100%; height:" +
document.height + "px'></div>");
$("div#svg").svg();
window.svg = $("div#svg").svg('get');
Also your going to need assign functions to listen for when the mouse is pressed and released and disable the ability to click on anything on the page so your not accidentally clicking a link and leaving the page as you try to draw.
$("body").bind("click", function(e) { return false; });
$("body").bind("mousedown", startingDrawing);
$("body").bind("mouseup", endingDrawing);
4. Drawing
Simple enough now. When the mouse is pressed start the mousemove listener and draw a line from the previous mouse position to the next one, and then turn back off the mousemove listener when the mouse button is released.
window.oldX;
window.oldY;
window.startingDrawing = function(event) {
window.oldX = event.pageX;
window.oldY = event.pageY;
$(document).bind("mousemove", mouseMoving);
return false;
}
window.mouseMoving = function(event) {
window.svg.line(null, window.oldX, window.oldY,
event.pageX, event.pageY,
{'stroke': window.STROKE_COLOR,
'stroke-width': window.STROKE_WIDTH});
window.oldX = event.pageX;
window.oldY = event.pageY;
}
window.endingDrawing = function(event) {
$(document).unbind('mousemove', mouseMoving);
}
The full script with all the other little details like support for enabling and disabling the script with a keyboard shortcut is available here. The download page also works as a live demo and runs an alternate way not involving Greasemonkey so you can test how the script would work without needing to download it and Greasemonkey.
Comments
Great job!
Anyway, for such advanced usages and for high concurrency computations, the best solution is building an own plugin to have workerthreads and caching in the chrome (no need to rebuild the SVGDOM each time ^_^” )