【问题标题】:Using Konva, how can I select and transform images?使用 Konva,我如何选择和转换图像?
【发布时间】:2020-06-25 11:13:01
【问题描述】:

我对 javascript 很陌生,我一直在关注 https://konvajs.org/ 的教程来帮助我学习他们的库。

我目前正在尝试制作它,以便您可以加载和选择本地图像以移动、调整大小和旋转它们。

这是我目前的代码:

  <head>
    <!-- USE DEVELOPMENT VERSION -->
    <script src="https://unpkg.com/konva@7.0.0/konva.min.js"></script>
    <meta charset="utf-8" />
    <title>Konva Select and Transform Demo</title>
    <style>
      body {
        margin: 0;
        padding: 0;
        overflow: hidden;
      }
    </style>
  </head>

  <body>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script        src="https://cdnjs.cloudflare.com/ajax/libs/konva/3.2.5/konva.min.js"></script>
<div>Render a local image without upload</div>
<div>
  <input type="file" id="file_input">
</div>
    <div id="container"></div>
    <script>
      var width = window.innerWidth;
      var height = window.innerHeight;

      var stage = new Konva.Stage({
        container: 'container',
        width: width,
        height: height,
      });

      var layer = new Konva.Layer();
      stage.add(layer);
        //add images
        // listen for the file input change event and load the image.
$("#file_input").change(function(e){

    var URL = window.webkitURL || window.URL;
    var url = URL.createObjectURL(e.target.files[0]);
    var img = new Image();
    img.src = url;


    img.onload = function() {

      var img_width = img.width;
      var img_height = img.height;

      // calculate dimensions to get max 300px
      var max = 300;
      var ratio = (img_width > img_height ? (img_width / max) : (img_height / max))

      // now load the Konva image
      var theImg = new Konva.Image({
        image: img,
        x: 50,
        y: 30,
        width: img_width/ratio,
        height: img_height/ratio,
        draggable: true,
        rotation: 0
      });

      layer.add(theImg);
      layer.draw();
    }


});
        


      var tr = new Konva.Transformer();
      layer.add(tr);

      // by default select all shapes
      

      // at this point basic demo is finished!!
      // we just have several transforming nodes
      layer.draw();

      // add a new feature, lets add ability to draw selection rectangle
      var selectionRectangle = new Konva.Rect({
        fill: 'rgba(0,0,255,0.5)',
      });
      layer.add(selectionRectangle);

      var x1, y1, x2, y2;
      stage.on('mousedown touchstart', (e) => {
        // do nothing if we mousedown on eny shape
        if (e.target !== stage) {
          return;
        }
        x1 = stage.getPointerPosition().x;
        y1 = stage.getPointerPosition().y;
        x2 = stage.getPointerPosition().x;
        y2 = stage.getPointerPosition().y;

        selectionRectangle.visible(true);
        selectionRectangle.width(0);
        selectionRectangle.height(0);
        layer.draw();
      });

      stage.on('mousemove touchmove', () => {
        // no nothing if we didn't start selection
        if (!selectionRectangle.visible()) {
          return;
        }
        x2 = stage.getPointerPosition().x;
        y2 = stage.getPointerPosition().y;

        selectionRectangle.setAttrs({
          x: Math.min(x1, x2),
          y: Math.min(y1, y2),
          width: Math.abs(x2 - x1),
          height: Math.abs(y2 - y1),
        });
        layer.batchDraw();
      });

      stage.on('mouseup touchend', () => {
        // no nothing if we didn't start selection
        if (!selectionRectangle.visible()) {
          return;
        }
        // update visibility in timeout, so we can check it in click event
        setTimeout(() => {
          selectionRectangle.visible(false);
          layer.batchDraw();
        });

        var shapes = stage.find('.rect').toArray();
        var box = selectionRectangle.getClientRect();
        var selected = shapes.filter((shape) =>
          Konva.Util.haveIntersection(box, shape.getClientRect())
        );
        tr.nodes(selected);
        layer.batchDraw();
      });

      // clicks should select/deselect shapes
      stage.on('click tap', function (e) {
        // if we are selecting with rect, do nothing
        if (selectionRectangle.visible()) {
          return;
        }

        // if click on empty area - remove all selections
        if (e.target === stage) {
          tr.nodes([]);
          layer.draw();
          return;
        }

        // do nothing if clicked NOT on our rectangles
        if (!e.target.hasName('rect')) {
          return;
        }

        // do we pressed shift or ctrl?
        const metaPressed = e.evt.shiftKey || e.evt.ctrlKey || e.evt.metaKey;
        const isSelected = tr.nodes().indexOf(e.target) >= 0;

        if (!metaPressed && !isSelected) {
          // if no key pressed and the node is not selected
          // select just one
          tr.nodes([e.target]);
        } else if (metaPressed && isSelected) {
          // if we pressed keys and node was selected
          // we need to remove it from selection:
          const nodes = tr.nodes().slice(); // use slice to have new copy of array
          // remove node from array
          nodes.splice(nodes.indexOf(e.target), 1);
          tr.nodes(nodes);
        } else if (metaPressed && !isSelected) {
          // add the node into selection
          const nodes = tr.nodes().concat([e.target]);
          tr.nodes(nodes);
        }
        layer.draw();
      });
    </script>

演示:https://www.w3schools.com/code/tryit.asp?filename=GG5QCXFMLFXJ

我不确定如何在图像而不是矩形上进行选择。

谢谢

【问题讨论】:

  • 嗨,欢迎月亮。我想祝贺你写了一个完美的问题,它清晰、简洁、易于理解你在寻找什么。一个很好的例子!

标签: javascript html image konvajs


【解决方案1】:

在演示中,您将看到“rect”名称用于检测可选形状。这是一种有用的方法,因为舞台上可能有不可选择的形状(如背景)。

所以要检查一个形状是否可选,我们使用:

e.target.hasName('rect')

所以请记住在舞台上的新图像中添加“rect”名称:

// now load the Konva image
var theImg = new Konva.Image({
        name: 'rect',
        image: img,
        x: 50,
        y: 30,
        width: img_width/ratio,
        height: img_height/ratio,
        draggable: true,
        rotation: 0
});

名称本身并不是很重要。您可以找到一种不同的方法来检测“可选”节点。

https://www.w3schools.com/code/tryit.asp?filename=GG6XVLB39IKW

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-07
    • 1970-01-01
    • 2020-10-04
    相关资源
    最近更新 更多