【问题标题】:Resizing the images while keeping proportion using kinetic js canvas使用动态 js 画布在保持比例的同时调整图像大小
【发布时间】:2012-10-19 19:58:50
【问题描述】:

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

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

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

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

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

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

【问题讨论】:

    标签: javascript image html html5-canvas kineticjs


    【解决方案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);
    

    【讨论】:

    • 谢谢,约瑟夫 Fneisz ! :)
    【解决方案2】:

    我知道这不是问题,但是当锚超出图像 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());
    

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

    希望这对某人有所帮助!

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

      • 非常好,请您发布一个具有最小高度和宽度限制的新示例。那太好了!
      • 只需将 kinetic.js 指向一个有效的 URL,这就像一个魅力。
      • @dwieme 请帮我解决问题stackoverflow.com/questions/61237506/…
      【解决方案4】:

      换行:

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

      Example

      【讨论】:

      • 嗯..这是我的问题..如何更改锚逻辑..我已经知道如何保持纵横比..
      猜你喜欢
      • 2021-06-12
      • 1970-01-01
      • 2013-08-17
      • 2017-06-02
      • 1970-01-01
      • 2023-01-09
      • 1970-01-01
      • 2012-03-12
      • 1970-01-01
      相关资源
      最近更新 更多