比例缩放和使用锚点拉伸图像

时间:2013-03-21 09:23:47

标签: javascript html5 kineticjs

我有一个包含8个锚点的图像。感谢example,我设法让4个角落的人只能缩放图片。但是我很难让其他4只能拉伸图像。

midTop& midBottom锚应垂直伸展; midLeft和midRight锚应水平伸展。我认为它可能涉及这些锚点可以移动的范围,但我不知道如何继续。

http://jsfiddle.net/Dppm7/3/(抱歉无法在jsFiddle中使用此功能)..

输出看起来像this.

请有人帮忙。 :)

锚点的一些代码(并非所有中间锚点的代码都已实现):

// Update the positions of handles during drag.
// This needs to happen so the dimension calculation can use the
// handle positions to determine the new width/height.
switch (activeHandleName) {
    case "topLeft":
        topRight.setY(activeHandle.getY());
        midRight.setY(activeHandle.getY());
        midTop.setY(activeHandle.getY());
        bottomLeft.setX(activeHandle.getX());
        midLeft.setX(activeHandle.getX());
        midBottom.setX(activeHandle.getX());
        break;
    case "topRight":
        topLeft.setY(activeHandle.getY());
        midLeft.setY(activeHandle.getY());
        midTop.setY(activeHandle.getY());
        bottomRight.setX(activeHandle.getX());
        midBottom.setX(activeHandle.getX());
        midRight.setX(activeHandle.getX());
        break;
    case "bottomRight":
        bottomLeft.setY(activeHandle.getY());
        midBottom.setY(activeHandle.getY());
        midLeft.setY(activeHandle.getY());
        topRight.setX(activeHandle.getX());
        midTop.setX(activeHandle.getX());
        midRight.setX(activeHandle.getX());
        break;
    case "bottomLeft":
        bottomRight.setY(activeHandle.getY());
        midBottom.setY(activeHandle.getY());
        midRight.setY(activeHandle.getY());
        topLeft.setX(activeHandle.getX());
        midTop.setX(activeHandle.getX());
        midLeft.setX(activeHandle.getX());
        break;
    case "midTop":
        topRight.setY(activeHandle.getY());
        topLeft.setY(activeHandle.getY());
        midRight.setY(activeHandle.getY());
        midLeft.setY(activeHandle.getY());
        break;
    case "midBottom":
        bottomRight.setY(activeHandle.getY());
        bottomLeft.setY(activeHandle.getY());
        midRight.setY(activeHandle.getY());
        midLeft.setY(activeHandle.getY());
        break;
    case "midRight":
        topRight.setX(activeHandle.getX());
        bottomRight.setX(activeHandle.getX());
        midTop.setX(activeHandle.getX());
        midBottom.setX(activeHandle.getX());
        break;
    case "midLeft":
        topLeft.setX(activeHandle.getX());
        bottomLeft.setX(activeHandle.getX());
        midTop.setX(activeHandle.getX());
        midBottom.setX(activeHandle.getX());
        break;
}

// Calculate new dimensions. Height is simply the dy of the handles.
// Width is increased/decreased by a factor of how much the height changed.
newHeight = bottomLeft.getY() - topLeft.getY();
newWidth = image.getWidth() * newHeight / image.getHeight();

// Move the image to adjust for the new dimensions.
// The position calculation changes depending on where it is anchored.
// ie. When dragging on the right, it is anchored to the top left,
//     when dragging on the left, it is anchored to the top right.
if (activeHandleName === "topRight" || activeHandleName === "bottomRight") {
    image.setPosition(topLeft.getX(), topLeft.getY());
} else if (activeHandleName === "topLeft" || activeHandleName === "bottomLeft") {
    image.setPosition(topRight.getX() - newWidth, topRight.getY());
}

imageX = image.getX();
imageY = image.getY();

// Update handle positions to reflect new image dimensions
topLeft.setPosition(imageX, imageY);
topRight.setPosition(imageX + newWidth, imageY);
bottomRight.setPosition(imageX + newWidth, imageY + newHeight);
bottomLeft.setPosition(imageX, imageY + newHeight);

midTop.setPosition(imageX + image.getWidth() / 2, imageY);
midBottom.setPosition(imageX + image.getWidth() / 2, imageY + newHeight);
midRight.setPosition(imageX + image.getWidth(), imageY + image.getHeight() / 2);
midLeft.setPosition(imageX, imageY + image.getHeight() / 2);

// Set the image's size to the newly calculated dimensions
if (newWidth && newHeight) {
    image.setSize(newWidth, newHeight);
}
}

1 个答案:

答案 0 :(得分:0)

<script>
    var imWidth;
    var imHeight;
    var topRight;
    var topLeft;
    var bottomLeft;
    var width;
    var height;
    var group;
    var bottomRight;
    var image;
    var aspectRatio;
    var oldwidth;
    var oldheight;
    var oldtopleftX;
    var oldtopleftY;
    var shrinkLimitBound;

  function update(activeAnchor) {
    group = activeAnchor.getParent();
    var anchorX = activeAnchor.getX();
    var anchorY = activeAnchor.getY();
    actRatio=imWidth/imHeight;
    shrinkLimitBound=100;
    height=bottomLeft.getY() - topLeft.getY();
    width=topRight.getX() - topLeft.getX();
    newRatio=(width)/(height);
    width=actRatio*height;
    switch (activeAnchor.getName()) {
      case 'topLeft':
        if(height<shrinkLimitBound)
        {
          height=shrinkLimitBound;
          width=actRatio*height;;
          topRight.setY(bottomRight.getY()-height);
        }
        else
        { 
          if(anchorY < bottomRight.getY())
            topRight.setY(anchorY);
          else
            topRight.setY(bottomRight.getY()-height);
        }
        topRight.setX(bottomRight.getX());
        bottomLeft.setX(bottomRight.getX()-width);
        bottomLeft.setY(bottomRight.getY());
        topLeft.setX(bottomRight.getX()-width);
        topLeft.setY(bottomRight.getY()-height);
        break;
      case 'topRight':
        if(height<shrinkLimitBound)
        {
          height=shrinkLimitBound;
          width=actRatio*height;;
          topLeft.setY(bottomLeft.getY()-height);
        }
        else
        { 
          if(anchorY < bottomLeft.getY()-shrinkLimitBound)
          {
            topLeft.setY(anchorY)
          }
          else
          {
            topLeft.setY(bottomLeft.getY()-height);
          }
        }
        topLeft.setX(bottomLeft.getX());
        bottomRight.setX(bottomLeft.getX()+width);
        bottomRight.setY(bottomLeft.getY());
        topRight.setX(bottomLeft.getX()+width);
        topRight.setY(bottomLeft.getY()-height);
        break;
      case 'bottomRight':
        if(height<shrinkLimitBound)
        {
          height=shrinkLimitBound;
          width=actRatio*height;;
          bottomLeft.setY(topLeft.getY()+height);
        }
        else
        { 
          if(anchorY > topLeft.getY()+shrinkLimitBound)
          {
            bottomLeft.setY(anchorY);
          }
          else
             bottomLeft.setY(topLeft.getY()+height);
        }
        bottomLeft.setX(topLeft.getX());
        topRight.setX(topLeft.getX()+width);
        topRight.setY(topLeft.getY());
        bottomRight.setX(topLeft.getX()+width);
        bottomRight.setY(topLeft.getY()+height);
        break;
      case 'bottomLeft':
        if(height<shrinkLimitBound)
        {
          height=shrinkLimitBound;
          width=actRatio*height;;
          bottomRight.setY(topRight.getY()+height);
        }
        else
        { 
          if(anchorY > topRight.getY())
            bottomRight.setY(anchorY);
          else
            bottomRight.setY(topRight.getY()+height);
        }
        bottomRight.setX(topRight.getX());
        topLeft.setX(topRight.getX()-width);
        topLeft.setY(topRight.getY());
        bottomLeft.setX(topRight.getX()-width);
        bottomLeft.setY(topLeft.getY()+height);
        break;
    }
    image.setPosition(topLeft.getPosition());
    if(width>0 && height>0)
    {
      image.setSize(width,height);
    }
    oldwidth=width;
    oldheight=height;
    oldtopleftX=topLeft.getX();
    oldtopleftY=topLeft.getY();

  }

  function addAnchor(group, x, y, name) {
    var stage = group.getStage();
    var layer = group.getLayer();
    var anchor = new Kinetic.Circle({
      x: x,
      y: y,
      stroke: '#666',
      fill: '#ddd',
      strokeWidth: 0,
      radius: 4,
      name: name,
      draggable: true,
      dragOnTop: false
    });

    anchor.on('dragmove', function() {

      update(this);
      layer.draw();

    });
    anchor.on('mousedown touchstart', function() {
      group.setDraggable(false);
      this.moveToTop();
    });
    anchor.on('dragend', function() {
      group.setDraggable(true);
      layer.draw();
    });
    // add hover styling
    anchor.on('mouseover', function() {
      var layer = this.getLayer();
      document.body.style.cursor = 'pointer';
      this.setStrokeWidth(4);
      layer.draw();
    });
    anchor.on('mouseout', function() {
      var layer = this.getLayer();
      document.body.style.cursor = 'default';
      this.setStrokeWidth(2);
      layer.draw();
    });

    group.add(anchor);
  }

  function loadImages(sources, callback) {
    var images = {};
    var loadedImages = 0;
    var numImages = 0;
    for(var src in sources) {
      numImages++;
    }
    for(var src in sources) {
      images[src] = new Image();
      images[src].onload = function() {
        if(++loadedImages >= numImages) {
          callback(images);
        }
      };
      images[src].src = sources[src];
    }
  }

  function initStage(images) {
    var conWidth = 578; //container Width.
    var conHeight = 400;    //container Heitgh.
    imWidth = images.dressTrailImage.width;
    imHeight = images.dressTrailImage.height;
    if (imWidth > conWidth)
    {
        imHeight = (imHeight/imWidth)*conWidth; 
        imWidth = conWidth;
    }
    if (imHeight > conHeight)
    {
        imWidth = (imWidth/imHeight)*conHeight; 
        imHeight = conHeight;
    }
    if ((imHeight < conHeight) && (imWidth < conWidth))
    {
        var diffX = conWidth - imWidth;
        var diffY = conHeight - imHeight;

        var diffY2 = (imHeight/imWidth)*diffX;

        if (diffY2 > diffY)
        {
            imWidth = (imWidth/imHeight)*conHeight; 
            imHeight = conHeight;
        }   
        else
        {
            imHeight = (imHeight/imWidth)*conWidth; 
            imWidth = conWidth;
        }       
    }
    images.UsrTrail.width = imWidth;
    images.UsrTrail.height = imHeight;
    var stage = new Kinetic.Stage({
      container: 'container',
      width: imWidth,
      height: imHeight
    });
    var dressTrailImageGroup = new Kinetic.Group({
      x: 0,
      y: 0,
      draggable: true,

      //dragBoundFunc: function(pos) {

        // console.log(pos);
        // // var newX;
        // // var newY;
        // console.log(topLeft.x+","+bottomRight.y);
        // x1=topLeft.x;
        // x2=bottomRight.x;
        // y1=topLeft.y;
        // y2=bottomRight.y;
        // x=pos.x;
        // y=pos.y;
        // var calsign = ((x-x1)*(y-y2))-((y-y1)*(x-x2))
        // if (calsign < 0){
        //   return {
        //   x : pos.x,
        //   y : pos.y
        //   }
        // }else {
        //   return {
        //   x : 50,
        //   y : 50
        //   }
        //  }

        //}
        // if (pos.x < ){
        //   newX=10;
        // } 
        // else if ((pos.x+dressTrailImage.getWidth()) > stage.getWidth()-50){
        //     newX = stage.getWidth()-dressTrailImage.getWidth()-50;
        // }
        // else{
        //     newX = pos.x;
        // };


        // if(pos.y < 10){
        //     newY = 10;
        // }
        // else if((pos.y + dressTrailImage.getHeight()) > stage.getHeight()-50){
        //     newY = stage.getHeight()-dressTrailImage.getHeight()-50;
        // }
        // else {
        //     newY = pos.y;
        // }

        //console.log("newX:"+newX+", newY:"+newY);
        // return {
        //   x : newX,
        //   y : newY,
        // };
      //}
    });
    // UsrTrail
    var UsrTrailImg = new Kinetic.Image({
      x: 0,
      y: 0,
      image: images.UsrTrail,
      width: images.UsrTrail.width,
      height: images.UsrTrail.height,
      name: 'image'
    });
    var layer = new Kinetic.Layer();
    /*
     * go ahead and add the groups
     * to the layer and the layer to the
     * stage so that the groups have knowledge
     * of its layer and stage
     */
    layer.add(dressTrailImageGroup);
    layer.add(UsrTrailImg);
    stage.add(layer);
    UsrTrailImg.moveToBottom();
    intialAspRatio = images.dressTrailImage.width/images.dressTrailImage.height;
    console.log("aspectRatio is :"+intialAspRatio);

    // dress Trail Image

    var inith=200; //set this to the desired height of the dress that shows up initially
    var initw=intialAspRatio*inith;

    var neck_user_x=50;//from backend
    var neck_user_y=20;//from backend
    var neck_dress_x=50;//from backend
    var neck_dress_y=5;//from backend

//for getting the actual width and height of the User's Image
var UsrImgObjActual= new Image();
UsrImgObjActual.src=sources.UsrTrail;
UsrimgWidth=UsrImgObjActual.width;
UsrimgHeight=UsrImgObjActual.height;
//////////////////////////////////////////

    // var UsrimgWidth= 180;
    // var UsrimgHeight=270;
console.log("height Should Be 270 and is:"+UsrimgHeight);
console.log("Width Should Be 180 and is:"+UsrimgWidth);
    var dressimgWidth=initw;
    var dressimgHeight=inith;

    console.log("usertrail image width adn height"+images.UsrTrail.width+"::"+images.UsrTrail.height);
    console.log("neck user and dress resp"+neck_user_x+","+neck_user_y+','+neck_dress_x+','+neck_dress_y);

    var x_draw=((neck_user_x*UsrimgWidth)-(neck_dress_x*dressimgWidth));
    var y_draw=((neck_user_y*UsrimgHeight)-(neck_dress_y*dressimgHeight));

    x_draw=x_draw/100;
    y_draw=y_draw/100;

    console.log("xdraw and ydraw:"+x_draw+','+y_draw);

    //top left corner coordinates of the dress image.
    var initx=x_draw;
    var inity=y_draw;

    var dressTrailImage = new Kinetic.Image({
      x: initx,
      y: inity,
      image: images.dressTrailImage,
      name: 'image',
      width: initw,// images.dressTrailImage.width,
      height: inith //images.dressTrailImage.height
    });

    // dressTrailImage.width = 50;
    // dressTrailImage.height = dressTrailImage.width / intialAspRatio;

    // console.log(dressTrailImage.height);

    dressTrailImageGroup.add(dressTrailImage);
    addAnchor(dressTrailImageGroup, initx , inity, 'topLeft');
    addAnchor(dressTrailImageGroup, initx + initw , inity , 'topRight');
    addAnchor(dressTrailImageGroup, initx + initw , inity + inith, 'bottomRight');
    addAnchor(dressTrailImageGroup, initx , inity + inith, 'bottomLeft');
    topLeft = dressTrailImageGroup.get('.topLeft')[0];
    topRight = dressTrailImageGroup.get('.topRight')[0];
    bottomRight = dressTrailImageGroup.get('.bottomRight')[0];
    bottomLeft = dressTrailImageGroup.get('.bottomLeft')[0];
    image = dressTrailImageGroup.get('.image')[0];
    dressTrailImageGroup.on('dragstart', function() {
      this.moveToTop();
    });
    stage.draw();
  }
  var sources = {
    dressTrailImage: "http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg",
    UsrTrail:  "http://www.html5canvastutorials.com/demos/assets/yoda.jpg"
  };

  loadImages(sources, initStage);
  //function called on clicking the submit button.
  function Sunmit_fn(){
                //neck positions of the trail dress in percentages (assumed for now!).
                neckDressX=50;//in percentage.
                neckDressY=5;//in percentage.
                //height and width of the user image used in the canvas.
        //original here here is refered to the height and width used in the canavs
                var originalUserImgWidth = imWidth; 
                var originalUserImgHeight = imHeight;
                var trailDressWidth = image.getWidth();//Final Image Width
                var trailDressHeight = image.getHeight();//Final Image Height
                imageX=topLeft.getParent().getX()+topLeft.getX()+1;//upper right anchor X Position 
                imageY=topLeft.getParent().getY()+topLeft.getY()+1;//upper right anchor Y Position
                //formula for calculating the final neck positions of the resized and dragged dress 
            //with respect to the user image in percentages
                neckFinalX=(imageX+(trailDressWidth*(neckDressX/100)))/originalUserImgWidth;
                neckFinalY=(imageY+(trailDressHeight*(neckDressY/100)))/originalUserImgHeight;
                //neck in percentages trail pic neck x,y.
                neckFinalX=neckFinalX*100;
                neckFinalY=neckFinalY*100;
        //Just for testing.
    console.log("neck position updated by User:");
        console.log("X:"+neckFinalX+", Y:"+neckFinalY+")");
        console.log("Resized Size of the dress is:");
        console.log("Width:"+trailDressWidth+", Height:"+trailDressHeight);
            }
</script>

此脚本仅沿一个轴调整四个点。您可以为所有点找出相同的内容