6角图像使用画布调整大小

时间:2014-03-30 15:17:01

标签: javascript html css canvas

我遇到了两个问题:

  1. 顶部中心,底部中心,左侧和右侧没有被堵塞
  2. 我没有得到改变图像大小的逻辑。
    1. 角落锚应按比例调整大小(高度和宽度,两者都应以相同的速率减少/增加。
    2. 非角色的人应该如下调整大小。
  3. 这是我预期的实施:

    my expected implementation

    我已经创建了一个画布,我在其上绘制图像并进行调整大小。这是我的HTML(非常简单:P):

    <canvas width="700px" height="700px" id="canvas"></canvas>
    

    以下是剧本:

    var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");
    
    //var canvasOffset = $("#canvas").offset();
    var offsetX = canvas.offsetLeft;
    var offsetY = canvas.offsetTop;
    
    var startX;
    var startY;
    var isDown = false;
    
    
    var pi2 = Math.PI * 2;
    var resizerRadius = 8;
    var rr = resizerRadius * resizerRadius;
    var draggingResizer = {
        x: 0,
        y: 0
    };
    var imageX = 50;
    var imageY = 50;
    var imageWidth, imageHeight, imageRight, imageBottom;
    var draggingImage = false;
    var startX;
    var startY;
    
    
    
    var img = new Image();
    img.onload = function () {
        imageWidth = img.width;
        imageHeight = img.height;
        imageRight = imageX + imageWidth;
        imageBottom = imageY + imageHeight
        draw(true, false);
    }
    img.src = 'img/' + localStorage["bgimgname"];
    
    
    function draw(withAnchors, withBorders) {
    
        // clear the canvas
        ctx.clearRect(0, 0, canvas.width, canvas.height);
    
        // draw the image
        ctx.drawImage(img, 0, 0, img.width, img.height, imageX, imageY, imageWidth, imageHeight);
    
        // optionally draw the draggable anchors
        if (withAnchors) {
            drawDragAnchor(imageX, imageY); //topleft
            drawDragAnchor((imageRight+imageX)/2, imageY); //topcenter
            drawDragAnchor(imageRight, imageY); //topright
    
            drawDragAnchor(imageX, (imageBottom+imageY)/2); //left
            drawDragAnchor(imageRight, (imageBottom+imageY)/2); //right
    
            drawDragAnchor(imageX, imageBottom); //bottomleft
            drawDragAnchor((imageRight+imageX)/2, imageBottom); //bottom center
            drawDragAnchor(imageRight, imageBottom); //bottomright
        }
    
        // optionally draw the connecting anchor lines
        if (withBorders) {
            ctx.beginPath();
            ctx.moveTo(imageX, imageY);
            ctx.lineTo(imageRight, imageY);
            ctx.lineTo(imageRight, imageBottom);
            ctx.lineTo(imageX, imageBottom);
            ctx.closePath();
            ctx.stroke();
        }
    
    }
    
    function drawDragAnchor(x, y) {
        ctx.beginPath();
        ctx.arc(x, y, resizerRadius, 0, pi2, false);
        ctx.closePath();
        ctx.fill();
    }
    
    function anchorHitTest(x, y) {
    
        var dx, dy;
    
        // top-left
        dx = x - imageX;
        dy = y - imageY;
        if (dx * dx + dy * dy <= rr) {
            return (0);
        }
    
        // top-center
        dx = (imageRight+imageX)/2
        dy = imageY
        if (dx/2 * dx/2 + dy * dy <= rr) {
            return (1);
        }
    
        // top-right
        dx = x - imageRight;
        dy = y - imageY;
        if (dx * dx + dy * dy <= rr) {
            return (2);
        }
    
        //left
        dx = imageX;
        dy = (imageBottom+imageY)/2
        if (dx * dx + dy/2 * dy/2 <= rr) {
            return (3);
        }
    
        //right
        dx = imageRight;
        dy = (imageBottom+imageY)/2
        if (dx * dx + dy/2 * dy/2 <= rr) {
            return (4);
        }
    
        // bottom-right
        dx = x - imageRight;
        dy = y - imageBottom;
        if (dx * dx + dy * dy <= rr) {
            return (5);
        }
    
        // bottom-center
        dx = (imageRight+imageX)/2;
        dy = imageBottom;
        if (dx/2 * dx/2 + dy * dy <= rr) {
            return (6);
        }
    
        // bottom-left
        dx = x - imageX;
        dy = y - imageBottom;
        if (dx * dx + dy * dy <= rr) {
            return (7);
        }
    
    
        return (-1);
    
    }
    
    
    function hitImage(x, y) {
        return (x > imageX && x < imageX + imageWidth && y > imageY && y < imageY + imageHeight);
    }
    
    
    function handleMouseDown(e) {
        startX = parseInt(e.clientX - offsetX);
        startY = parseInt(e.clientY - offsetY);
        draggingResizer = anchorHitTest(startX, startY);
        draggingImage = draggingResizer < 0 && hitImage(startX, startY);
    }
    
    function handleMouseUp(e) {
        draggingResizer = -1;
        draggingImage = false;
        draw(true, false);
    }
    
    function handleMouseOut(e) {
        handleMouseUp(e);
    }
    
    function handleMouseMove(e) {
        e = window.event;
        if (draggingResizer > -1) {
    
            mouseX = parseInt(e.clientX - offsetX);
            mouseY = parseInt(e.clientY - offsetY);
    
            // resize the image
            switch (draggingResizer) {
                case 0:
                    //top-left
                    console.log("topleft");
                    break;
                case 1:
                    //top-center
                    console.log("topcenter");
                    break;
                case 2:
                    //top-right
                    console.log("topright");
                    break;
                case 3:
                    //left
                    console.log("left");
                    break;
                case 4:
                    //right
                    console.log("right");
                    break;
                case 5:
                    //bottom-left
                    console.log("bottomleft");
                    break;
                case 6:
                    //center
                    console.log("bottomcenter");
                    break;
                case 7:
                    //bottom-right
                    console.log("bottomright");
                    break;
            }
    
            if(imageWidth<25){imageWidth=25;}
            if(imageHeight<25){imageHeight=25;}
            if(imageWidth>700){imageWidth=700;}
            if(imageHeight>700){imageHeight=700;}
            // set the image right and bottom
            imageRight = imageX + imageWidth;
            imageBottom = imageY + imageHeight;
    
            // redraw the image with resizing anchors
            draw(true, true);
    
        }
    
    
    }
    
    canvas.addEventListener('mousedown', handleMouseDown);
    canvas.addEventListener('mousemove', handleMouseMove);
    canvas.addEventListener('mouseup', handleMouseUp);
    canvas.addEventListener('mouseout', handleMouseOut);
    

    输出为:Output

    请你能解释一下为什么非角落的锚没有被点击,请告诉我根据锚点调整图像大小的逻辑如上所述并在图片中显示。请帮忙。 :)

    **注意:** jQuery根本不允许。

1 个答案:

答案 0 :(得分:1)

请在此处查看我的回答:Change origin of canvas drawn image

我正在重复下面的答案,以防有人搜索这个答案而不是另一个答案。

根据需要调整大小的一种有效方法是保持相对侧的位置固定,让所选侧浮动,拖动侧或角。

这种方法的另一个好处是你不需要锚!

这是操作系统窗口的工作方式。

调整窗口大小时,您没有可拖动的可用锚点,只需拖动窗口的侧面或角落即可。

演示:http://jsfiddle.net/m1erickson/keZ82/

  • 左:原始图片,
  • 中间:从左下角调整大小&amp;保持纵横比(右上角保持固定)
  • 右:从底部调整大小&amp;图像仅在y方向上缩放(图像顶部保持固定)

enter image description here enter image description here enter image description here

注意:此演示和示例显示锚点,但它们严格来说是装饰性的。您可以关闭锚点显示,并通过拖动图像的一侧或一角来调整图像大小。

示例代码:

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
    body{ background-color: ivory; }
    canvas{border:1px solid red;}
</style>
<script>
$(function(){

    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");
    var $canvas=$("#canvas");
    var canvasOffset=$canvas.offset();
    var offsetX=canvasOffset.left;
    var offsetY=canvasOffset.top;
    var isDown=false;

    var iW;
    var iH;
    var iLeft=50;
    var iTop=50;
    var iRight,iBottom,iOrientation;

    var img=new Image();
    img.onload=function(){
        iW=img.width;
        iH=img.height;
        iRight=iLeft+iW;
        iBottom=iTop+iH;
        iOrientation=(iW>=iH)?"Wide":"Tall";
        draw(true);
    }
    img.src="facesSmall.png";

    var border=10;
    var isLeft=false;
    var isRight=false;
    var isTop=false;
    var isBottom=false;
    var iAnchor;

    canvas.onmousedown=handleMousedown;
    canvas.onmousemove=handleMousemove;
    canvas.onmouseup=handleMouseup;
    canvas.onmouseout=handleMouseup;


    function hitResizeAnchor(x,y){

        // which borders are under the mouse
        isLeft=(x>iLeft && x<iLeft+border);
        isRight=(x<iRight && x>iRight-border);
        isTop=(y>iTop && y<iTop+border);
        isBottom=(y<iBottom && y>iBottom-border);

        // return the appropriate anchor
        if(isTop && isLeft){ return(iOrientation+"TL"); }
        if(isTop && isRight){ return(iOrientation+"TR"); }
        if(isBottom && isLeft){ return(iOrientation+"BL"); }
        if(isBottom && isRight){ return(iOrientation+"BR"); }
        if(isTop){ return("T"); }
        if(isRight){ return("R"); }
        if(isBottom){ return("B"); }
        if(isLeft){ return("L"); }
        return(null);
    }

    var resizeFunctions={

        T: function(x,y){ iTop=y; },
        R: function(x,y){ iRight=x; },
        B: function(x,y){ iBottom=y; },
        L: function(x,y){ iLeft=x; },

        WideTR: function(x,y){
            iRight=x;
            iTop=iBottom-(iH*(iRight-iLeft)/iW);
        },
        TallTR: function(x,y){
            iTop=y;
            iRight=iLeft+(iW*(iBottom-iTop)/iH);
        },

        WideBR: function(x,y){
            iRight=x;
            iBottom=iTop+(iH*(iRight-iLeft)/iW);
        },
        TallBR: function(x,y){
            iBottom=y;
            iRight=iLeft+(iW*(iBottom-iTop)/iH);
        },

        WideBL: function(x,y){
            iLeft=x;
            iBottom=iTop+(iH*(iRight-iLeft)/iW);
        },
        TallBL: function(x,y){
            iBottom=y;
            iLeft=iRight-(iW*(iBottom-iTop)/iH);
        },

        WideTL: function(x,y){
            iLeft=x;
            iTop=iBottom-(iH*(iRight-iLeft)/iW);
        },
        TallTL: function(x,y){
            iBottom=y;
            iLeft=iRight-(iW*(iBottom-iTop)/iH);
        }
    };

    function handleMousedown(e){
         // tell the browser we'll handle this mousedown
         e.preventDefault();
         e.stopPropagation();
         var mouseX=e.clientX-offsetX;
         var mouseY=e.clientY-offsetY;
         iAnchor=hitResizeAnchor(mouseX,mouseY);
         isDown=(iAnchor);
    }

    function handleMouseup(e){
         // tell the browser we'll handle this mouseup
         e.preventDefault();
         e.stopPropagation();
         isDown=false;
         draw(true);
    }

    function handleMousemove(e){
         // tell the browser we'll handle this mousemove
         e.preventDefault();
         e.stopPropagation();
         // return if we're not dragging
         if(!isDown){return;}
         // get MouseX/Y
         var mouseX=e.clientX-offsetX;
         var mouseY=e.clientY-offsetY;

         // reset iLeft,iRight,iTop,iBottom based on drag
         resizeFunctions[iAnchor](mouseX,mouseY);

         // redraw the resized image
         draw(false);
    }


    function draw(withAnchors){
        var cx=iLeft+(iRight-iLeft)/2;
        var cy=iTop+(iBottom-iTop)/2;
        ctx.clearRect(0,0,canvas.width,canvas.height);
        ctx.drawImage(img,iLeft,iTop,iRight-iLeft,iBottom-iTop);   
        if(withAnchors){
            ctx.fillRect(iLeft,iTop,border,border);
            ctx.fillRect(iRight-border,iTop,border,border);
            ctx.fillRect(iRight-border,iBottom-border,border,border);
            ctx.fillRect(iLeft,iBottom-border,border,border);
            ctx.fillRect(cx,iTop,border,border);
            ctx.fillRect(cx,iBottom-border,border,border);
            ctx.fillRect(iLeft,cy,border,border);
            ctx.fillRect(iRight-border,cy,border,border);
        }
    }

}); // end $(function(){});
</script>
</head>
<body>
    <h4>Drag image anchors</h4>
    <canvas id="canvas" width=300 height=300></canvas>
</body>
</html>