0

I'm currently trying to achieve the following. I have a HTML5 Canvas, where you can draw in. The code is this:

var canvas, ctx, flag = false,
            prevX = 0,
            currX = 0,
            prevY = 0,
            currY = 0,
            dot_flag = false;
    
        var x = "black",
            y = 2;
    
        function init() {
            canvas = document.getElementById('can');
            ctx = canvas.getContext("2d");
            w = canvas.width;
            h = canvas.height;
    
            canvas.addEventListener("mousemove", function (e) {
                findxy('move', e)
            }, false);
            canvas.addEventListener("mousedown", function (e) {
                findxy('down', e)
            }, false);
            canvas.addEventListener("mouseup", function (e) {
                findxy('up', e)
            }, false);
            canvas.addEventListener("mouseout", function (e) {
                findxy('out', e)
            }, false);
        }
    
        function color(obj) {
            switch (obj.id) {
                case "green":
                    x = "green";
                    break;
                case "blue":
                    x = "blue";
                    break;
                case "red":
                    x = "red";
                    break;
                case "yellow":
                    x = "yellow";
                    break;
                case "orange":
                    x = "orange";
                    break;
                case "black":
                    x = "black";
                    break;
                case "white":
                    x = "white";
                    break;
            }
            if (x == "white") y = 14;
            else y = 2;
    
        }
    
        function draw() {
            ctx.beginPath();
            ctx.moveTo(prevX, prevY);
            ctx.lineTo(currX, currY);
            ctx.strokeStyle = x;
            ctx.lineWidth = y;
            ctx.stroke();
            ctx.closePath();
        }
    
        function erase() {
            var m = confirm("Want to clear");
            if (m) {
                ctx.clearRect(0, 0, w, h);
                document.getElementById("canvasimg").style.display = "none";
            }
        }
    
        function save() {
            document.getElementById("canvasimg").style.border = "2px solid";
            var dataURL = canvas.toDataURL();
            document.getElementById("canvasimg").src = dataURL;
            document.getElementById("canvasimg").style.display = "inline";
        }
    
        function findxy(res, e) {
            if (res == 'down') {
                prevX = currX;
                prevY = currY;
                currX = e.clientX - canvas.offsetLeft;
                currY = e.clientY - canvas.offsetTop;
    
                flag = true;
                dot_flag = true;
                if (dot_flag) {
                    ctx.beginPath();
                    ctx.fillStyle = x;
                    ctx.fillRect(currX, currY, 2, 2);
                    ctx.closePath();
                    dot_flag = false;
                }
            }
            if (res == 'up' || res == "out") {
                flag = false;
            }
            if (res == 'move') {
                if (flag) {
                    prevX = currX;
                    prevY = currY;
                    currX = e.clientX - canvas.offsetLeft;
                    currY = e.clientY - canvas.offsetTop;
                    draw();
                }
            }
        }
<html>
        <body onload="init()">
            <canvas id="can" width="400" height="400" style="position:absolute;top:10%;left:10%;border:2px solid;"></canvas>
            <div style="position:absolute;top:12%;left:43%;">Choose Color</div>
            <div style="position:absolute;top:15%;left:45%;width:10px;height:10px;background:green;" id="green" onclick="color(this)"></div>
            <div style="position:absolute;top:15%;left:46%;width:10px;height:10px;background:blue;" id="blue" onclick="color(this)"></div>
            <div style="position:absolute;top:15%;left:47%;width:10px;height:10px;background:red;" id="red" onclick="color(this)"></div>
            <div style="position:absolute;top:17%;left:45%;width:10px;height:10px;background:yellow;" id="yellow" onclick="color(this)"></div>
            <div style="position:absolute;top:17%;left:46%;width:10px;height:10px;background:orange;" id="orange" onclick="color(this)"></div>
            <div style="position:absolute;top:17%;left:47%;width:10px;height:10px;background:black;" id="black" onclick="color(this)"></div>
            <div style="position:absolute;top:20%;left:43%;">Eraser</div>
            <div style="position:absolute;top:22%;left:45%;width:15px;height:15px;background:white;border:2px solid;" id="white" onclick="color(this)"></div>
            <img id="canvasimg" style="position:absolute;top:10%;left:52%;" style="display:none;">
            <input type="button" value="save" id="btn" size="30" onclick="save()" style="position:absolute;top:55%;left:10%;">
            <input type="button" value="clear" id="clr" size="23" onclick="erase()" style="position:absolute;top:55%;left:15%;">
        </body>
        </html>

So basically just drawing lines from one point to another.

Now I'm wondering about the following. Most of you should know OneNote, which has a feature that you can draw something, and then you see "whoops, this was drawn much to big or to small in comparison to the other things I have drawn" and then you can just mark it and grab the corner and make the rectangle you marked smaller or bigger.

I'm currently thinking about the same solution in a canvas. So people can draw something in that canvas, and there's a resize button, when you click on it, you can "draw" a rectangle (like with a dotted border and transparet fill) and everything in that rectangle is then marked. Then you can grab one of the corners and make the marked drawings smaller or bigger, and move that content as well.

But honestly, I have no idea how to get started with that. Anybody has an idea on how to do that?

gman
  • 100,619
  • 31
  • 269
  • 393
nameless
  • 1,483
  • 5
  • 32
  • 78
  • May be this can help. the following is about scaling image on canvas. but maybe helpfull for you https://stackoverflow.com/questions/19100009/dragging-and-resizing-an-image-on-html5-canvas/19101826#19101826 – M.suleman Khan Jul 28 '17 at 08:22
  • 1
    @M.sulemanKhan This definetely looks interesting, the question then only is on how to mark a specific area and use this area instead of an image – nameless Jul 28 '17 at 08:29

1 Answers1

0

Not that difficult:

  1. Create a button, attach an event listener, call a function. I’ll call it resize for the purpose of my guide
  2. Create the dotted border overlay over your canvas. Just make it a div, wrap the canvas into a wrapper, apply a bit of CSS. Voilà.
  3. Attach event handlers to the div to make it resizable or search the web for a library that can do that.
  4. Then you’ll have to redraw the canvas as image with CanvasRenderingContext2D.drawImage().

It’s worth noting that canvases are raster-graphics. The canvas will become unsharp with enlarging.

idmean
  • 14,540
  • 9
  • 54
  • 83
  • I think, you got one point wrong. I want to mark some drawings like only a bit of the drawings, say you write a mathematic formular and u notice you are running out of space, then you want to mark that part in the canvas and resize it and put it in the upper left corner for example, so you have more space again. – nameless Jul 28 '17 at 08:28
  • @nameless That’s what the div is for, isn’t it? You can have a create stage at which the users resizes it and a scale phase in which resizing the div resizes the underlying content in the canvas. – idmean Jul 28 '17 at 08:30
  • Not sure... How can the user mark the area that he want's to resizie in the example? Also how can he move it then? The Stackoverflow thread that I got pointed to in the comments looks promising, just not sure how to use it with a selected area instead of a picture – nameless Jul 28 '17 at 08:32
  • @nameless Make the div movable. Make it resizable. There’re plenty of JavaScript libraries that can help you, if you can’t write this yourself. Look at the documentation of `drawImage` I linked to. You can pass it parameters that specify the area you want to draw of the image (the image is the original canvas) and where you want to draw it. – idmean Jul 28 '17 at 08:34
  • and how do I specify the div? Again, I don't want to resize the hole canvas I want to select a specific part. How can I select it? And can you tell me one library so I know which ones you mean? – nameless Jul 28 '17 at 08:36
  • @nameless *How can I select it?* Have a look at `drawImage`’s parameters `sx, sy, sWidth, sHeight`. First google hit for `javascript library resize move` for me is: http://interactjs.io. Never tried that. – idmean Jul 28 '17 at 08:38
  • I saw that parameters in the doc, but however I mean how can "the user" select it? Ofcourse programatically I can then mark the area with the parameters but somehow the user has to select this area, like with drawing a transparent rectangle over that area... About the library: Can I just use any library like that? Because basically I have to move elements in the canvas, not the hole canvas, so isn't that something completely different? – nameless Jul 28 '17 at 08:41
  • I’ll try to explain it one last time: The users resizes and moves a div to select the source area. Then he clicks a button. This part is now the selected part. (Once that’s working you can still make him "draw" that area.) From now on moving and resizing the div will change the canvas. Whenever the div is changed, you take the original canvas, and draw the selected part of it with `drawImage` into the newly selected area. – idmean Jul 28 '17 at 08:43
  • NOW i got what you mean. You mean first the complete canvas gets an overlay, then this overlay can be changed in size and moved (to select the area that the user wants to resize), then he can click the resize button and do the same thing as before again (so resize that div), but now, not only the div size changes but also the content in the div (or underneath the div - in the canvas basically), correct? – nameless Jul 28 '17 at 08:47
  • Exactly. That’s what I meant and how I’d go about it. – idmean Jul 28 '17 at 08:49
  • okay, but I think there are still some points (at least one that directly comes in my mind) to note: When I now select an area, and then drag the corner to make it bigger, say the marked area is top left and i want to move it, then if I once move it over the complete canvas, everything else on the canvas is gone... Or do I think wrong here? Because basically if on every move, the canvas is redrawn, then I take theselected area as an image and move it. Once I move it over existing drawings, those are lost.. correct? – nameless Jul 28 '17 at 08:52
  • If you do it like this, yes. [But I’d copy the canvas first.](https://stackoverflow.com/questions/4405336/how-to-copy-contents-of-one-canvas-to-another-canvas-locally) Then you can always copy from there and restore it to that if the users wants to cancel. There may also be other obstacles. You asked for an idea how to do that. Nobody here will present you a full solution to a whole task like this. – idmean Jul 28 '17 at 08:55
  • Sure. Thanks for you help. I will see, if I can get this running. – nameless Jul 28 '17 at 08:56