1

我在我的应用程序中使用它:

http://www.html5canvastutorials.com/labs/html5-canvas-drag-and-drop-resize-and-invert-images/

使用锚来调整图像大小..

我想要的是调整图像大小并保持其比例。我不希望它伸展我能够使用这种和平的代码来实现这一点。:..

  if(width) {
        image.setSize(width);
      }

但这搞砸了锚点..任何人都尝试过这样的事情..

4

4 回答 4

10

我知道这是一个非常古老的帖子,但我需要实现这个确切的东西,并且发现公认的答案有很大的缺陷 - 例如,左侧的两个拖动手柄移动整个图像并且其行为与图像编辑程序非常不同。我正在发布我的解决方案,以防有人像我一样从谷歌搜索中偶然发现这个问题。

// 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());
        bottomLeft.setX(activeHandle.getX());
        break;
    case "topRight":
        topLeft.setY(activeHandle.getY());
        bottomRight.setX(activeHandle.getX());
        break;
    case "bottomRight":
        bottomLeft.setY(activeHandle.getY());
        topRight.setX(activeHandle.getX());
        break;
    case "bottomLeft":
        bottomRight.setY(activeHandle.getY());
        topLeft.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);

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

JSBin 中修改的 KineticJS 示例:http: //jsbin.com/iyimuy/1/edit

于 2013-02-01T20:56:37.143 回答
1

换行:

var width = topRight.attrs.x - topLeft.attrs.x;
var height = bottomLeft.attrs.y - topLeft.attrs.y;
if(width && height) {
    image.setSize(width, height);
}

到:

var height = bottomLeft.attrs.y - topLeft.attrs.y;
var width = image.getWidth()*height/image.getHeight();

topRight.attrs.x = topLeft.attrs.x + width;
topRight.attrs.y = topLeft.attrs.y;
bottomRight.attrs.x = topLeft.attrs.x + width;
bottomRight.attrs.y = topLeft.attrs.y + height;

if(width && height) {
    image.setSize(width, height);
}

例子

于 2012-10-30T23:47:04.783 回答
1

这是:JSFIDDLE

JS:

function update(group, activeHandle) {
        var topLeft = group.get(".topLeft")[0],
            topRight = group.get(".topRight")[0],
            bottomRight = group.get(".bottomRight")[0],
            bottomLeft = group.get(".bottomLeft")[0],
            image = group.get(".image")[0],
            activeHandleName = activeHandle.getName(),
            newWidth,
            newHeight,
            minWidth = 32,
            minHeight = 32,
            oldX,
            oldY,
            imageX,
            imageY;

        // 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":
                oldY = topRight.getY();
                oldX = bottomLeft.getX();
                topRight.setY(activeHandle.getY());
                bottomLeft.setX(activeHandle.getX());
                break;
            case "topRight":
                oldY = topLeft.getY();
                oldX = bottomRight.getX();
                topLeft.setY(activeHandle.getY());
                bottomRight.setX(activeHandle.getX());
                break;
            case "bottomRight":
                oldY = bottomLeft.getY();
                oldX = topRight.getX();
                bottomLeft.setY(activeHandle.getY());
                topRight.setX(activeHandle.getX());
                break;
            case "bottomLeft":
                oldY = bottomRight.getY();
                oldX = topLeft.getX();
                bottomRight.setY(activeHandle.getY());
                topLeft.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();

        // It's too small: move the active handle back to the old position
        if( newWidth < minWidth || newHeight < minHeight ){
          activeHandle.setY(oldY);
          activeHandle.setX(oldX);
          switch (activeHandleName) {
            case "topLeft":
                topRight.setY(oldY);
                bottomLeft.setX(oldX);
                break;
            case "topRight":
                topLeft.setY(oldY);
                bottomRight.setX(oldX);
                break;
            case "bottomRight":
                bottomLeft.setY(oldY);
                topRight.setX(oldX);
                break;
            case "bottomLeft":
                bottomRight.setY(oldY);
                topLeft.setX(oldX);
                break;
          }
        }


        newHeight = bottomLeft.getY() - topLeft.getY();
        //comment the below line and uncomment the line below tha line to allow free resize of the images because the below line preserves the scale and aspect ratio
        newWidth = image.getWidth() * newHeight / image.getHeight();//for restricted resizing
        //newWidth = topRight.getX() - topLeft.getX();//for free resizing

        // 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);

        // Set the image's size to the newly calculated dimensions
        if(newWidth && newHeight) {
            image.setSize(newWidth, newHeight);
        }
      }
      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: 2,
          radius: 8,
          name: name,
          draggable: true
        });

        anchor.on("dragmove", function() {
          update(group, 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 stage = new Kinetic.Stage({
          container: "container",
          width: 578,
          height: 400
        });
        var darthVaderGroup = new Kinetic.Group({
          x: 270,
          y: 100,
          draggable: true
        });
        var yodaGroup = new Kinetic.Group({
          x: 100,
          y: 110,
          draggable: true
        });
        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(darthVaderGroup);
        layer.add(yodaGroup);
        stage.add(layer);

        // darth vader
        var darthVaderImg = new Kinetic.Image({
          x: 0,
          y: 0,
          image: images.darthVader,
          width: 200,
          height: 138,
          name: "image"
        });

        darthVaderGroup.add(darthVaderImg);
        addAnchor(darthVaderGroup, 0, 0, "topLeft");
        addAnchor(darthVaderGroup, 200, 0, "topRight");
        addAnchor(darthVaderGroup, 200, 138, "bottomRight");
        addAnchor(darthVaderGroup, 0, 138, "bottomLeft");

        darthVaderGroup.on("dragstart", function() {
          this.moveToTop();
        });
        // yoda
        var yodaImg = new Kinetic.Image({
          x: 0,
          y: 0,
          image: images.yoda,
          width: 93,
          height: 104,
          name: "image"
        });

        yodaGroup.add(yodaImg);
        addAnchor(yodaGroup, 0, 0, "topLeft");
        addAnchor(yodaGroup, 93, 0, "topRight");
        addAnchor(yodaGroup, 93, 104, "bottomRight");
        addAnchor(yodaGroup, 0, 104, "bottomLeft");

        yodaGroup.on("dragstart", function() {
          this.moveToTop();
        });

        stage.draw();
      }

      var sources = {
        darthVader: 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg',
        yoda: 'http://www.html5canvastutorials.com/demos/assets/yoda.jpg'
      };
      loadImages(sources, initStage);
于 2014-02-03T05:30:56.010 回答
0

我知道这不是问题,但是当锚超出图像 0 大小时,我已经浪费了很多时间来尝试解决问题,这会引发 javasacript 错误:

IndexSizeError: Index or size is negative or greater than the allowed amount

我所做的是将 Math.abs 添加到图像大小计算公式中:

newHeight = Math.abs(bottomLeft.getY() - topLeft.getY()); 
newWidth = Math.abs(image.getWidth() * newHeight / image.getHeight());

它适用于两个底部锚点,但不适用于顶部锚点,我刚刚移除了顶部锚点,这对我的项目来说是足够好的解决方案......

希望这对某人有帮助!

于 2013-11-19T10:59:59.623 回答