Search code examples
imagecanvasgreasemonkey

greasemonkey canvas script


Recently I've been working on a Greasemonkey script that would add an image to a certain page, http://fairview.deadfrontier.com to be exact, with a feature that would allow to draw on the added image.

I'm not experienced with JavaScript so after a painful and long process I have managed to create a stand-alone block of script that would do the job and it works just fine when used off-line in a .htm file.

But, when I upload the script to userscripts.org and install in Greasemonkey it stops working. I would appreciate any ideas or solutions that would help me finish the script so I can share it. Here is the script in question in a single .htm file:

<script type="text/javascript">
window.onload = function() {

    var oCanvas = document.getElementById("thecanvas");
      var oCtx = oCanvas.getContext("2d");

    var iWidth = oCanvas.width;
    var iHeight = oCanvas.height;

    oCtx.fillStyle = "transparent";
    oCtx.fillRect(0,0,iWidth,iHeight);

    oCtx.beginPath();
    oCtx.strokeStyle = "rgb(255,0,0)";

    oCanvas.onmousedown = function(e) {
        bMouseIsDown = true;
        iLastX = e.clientX - oCanvas.offsetLeft + (window.pageXOffset||document.body.scrollLeft||document.documentElement.scrollLeft);
        iLastY = e.clientY - oCanvas.offsetTop + (window.pageYOffset||document.body.scrollTop||document.documentElement.scrollTop);
    }
    oCanvas.onmouseup = function() {
        bMouseIsDown = false;
        iLastX = -1;
        iLastY = -1;
    }
    oCanvas.onmousemove = function(e) {
        if (bMouseIsDown) {
            var iX = e.clientX - oCanvas.offsetLeft + (window.pageXOffset||document.body.scrollLeft||document.documentElement.scrollLeft);
            var iY = e.clientY - oCanvas.offsetTop + (window.pageYOffset||document.body.scrollTop||document.documentElement.scrollTop);
            oCtx.moveTo(iLastX, iLastY);
            oCtx.lineTo(iX, iY);
            oCtx.stroke();
            iLastX = iX;
            iLastY = iY;
        }
    }
}
document.write("<canvas width=\"356\" height=\"700\" style=\"border: 1px solid black; background-image:url('http:\/\/i.imgur.com\/fI3qz.jpg'); position:fixed; top:10px; left: 10px;\" id=\"thecanvas\"><\/canvas>");
</script>

Solution

  • OK, here are the issues I saw with that file (canvas.htm), in regards to converting to GM, and in general.
    Most serious first:

    1. Don't/can't use document.write. Use something like:

      var zNode       = document.createElement ('canvas');
      zNode.setAttribute ('id', 'thecanvas');
      document.body.appendChild (zNode);
      


    2. In Greasemonkey, event handlers can't be set like:

      oCanvas.onmousedown = function(e) { ... ...

      Use:

      oCanvas.addEventListener
      (
          "mousedown",
          function (e)
          {
              bMouseIsDown = true;
              iLastX = e.clientX - oCanvas.offsetLeft + (window.pageXOffset||document.body.scrollLeft||document.documentElement.scrollLeft);
              iLastY = e.clientY - oCanvas.offsetTop + (window.pageYOffset||document.body.scrollTop||document.documentElement.scrollTop);
          },
          true
      );
      


    3. Don't use inline styles, you'll save yourself a ton of grief. If you create the canvas node, per item 1, then you can use this Greasemonkey to style it:

      GM_addStyle ( (<><![CDATA[
          #thecanvas
          {
              width:              356px;
              height:             700px;
              border:             1px solid black;
              background-image:   url('https://i.sstatic.net/fI3qz.jpg');
              position:           fixed;
              top:                10px;
              left:               10px;
          }
      ]]></>).toString () );
      


    4. The X/Y math is off, when considering a canvas as part of a larger page.

    5. bMouseIsDown seems to be used as a global variable; it should be set as such.


    Anyhow, that should be enough to get your GM script working, to start. If so, mark this question as answered.
    For any follow-up questions, include the full code of the script in the question body (but code-formatted for StackOverflow).