javascript 如何在Konva js stage上处理图像(溢出,可拖动区域等)?

kb5ga3dv  于 2023-05-12  发布在  Java
关注(0)|答案(1)|浏览(377)

我正在尝试使用konva.js创建一个舞台。基本上,我需要添加两个(至少)或更多的图像在舞台上的基础上一些布局。

示例:

我有一个布局,分裂舞台面积垂直成两个类似的群体。每个组有一个图像。

示例代码:

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

var layer = new Konva.Layer({
              imageSmoothingEnabled: true
});

// add a vertical line in order to show seperated groups
var line = new Konva.Line({
              points: [stage.width() / 2, 0, stage.width() / 2, stage.height()],
              stroke: '#9499a3',
              strokeWidth: 2,
              lineCap: 'round',
              lineJoin: 'round',
});
layer.add(line)

// create group #1
var group1 = new Konva.Group({
             x: 0,
             y: 0,
             width: stage.width() / 2,
             height: stage.height()
});

var image1;
var imageObj = new Image();
imageObj.onload = function () {
                    
                    image1 = new Konva.Image({
                        x: (stage.width() / 2 - imageObj.width) - line.strokeWidth() / 2,
                        //y: 0,
                        width: imageObj.width,
                        height: stage.height(),
                        image: imageObj,
                        draggable: true,
                    });

                    //layer.add(image1);
                    group1.add(image1);

                    image1.on('dragstart', function () {
                        console.log('dragstart')
                    });

                    image1.on('dragmove', function(e){
                        console.log('X : ' + this.attrs.x + ', Y : ' + this.attrs.y)
                    });

                    image1.on('dragend', function () {
                        console.log('X : ' + this.attrs.x + ', Y : ' + this.attrs.y)
                    });
};
imageObj.src = 'img/1.jpg';

// create group #2
var group2 = new Konva.Group({
                x: stage.width() / 2  + line.strokeWidth() / 2,
                y: 0,
                width: stage.width() / 2,
                height: stage.height()
});

var image2;
var imageObj = new Image();
imageObj.onload = function () {

                    image2 = new Konva.Image({
                        //x: stage.width() / 2  + line.strokeWidth() / 2,
                        //y: stage.height() / 2 - imageObj.height / 2,
                        width: imageObj.width,
                        height: stage.height(),
                        image: imageObj,
                        draggable: true,
                    });
                    
                    //layer.add(image2);
                    group2.add(image2);
};
imageObj.src = 'img/2.jpg';

layer.add(group1, group2)
stage.add(layer);

我想做的事:

  • 定义每个图像(或组)的可拖动区域,以便彼此之间不溢出。
  • 检查层是否可见,以便重新定位图像以隐藏层。
lnlaulya

lnlaulya1#

因此,实现这一点的方法是使用一个rect来定义图像将被约束的帧。将其放入一个组中,并设置组的剪辑区域以匹配帧矩形的位置和大小。现在将图像添加到组中。只有组中的图像部分可见。
额外的好处是,如果您将dragBoundFunc添加到组中,则可以确保无法将过大的图像拖动到帧边缘之外。
请参阅下面的片段(最好全屏运行)和可编辑的CodePen here
当然,这只是一个图像帧,您已经描述了在您的用例中将有两个图像帧。我建议你解开代码,然后创建一个类,然后你可以根据需要使用尽可能多的类,等等。

// this data gives the position and size of the frame
let data = {
  frameGroup: { x: 50, y: 100, width: 800, height: 300, strokeWidth: 10, stroke: 'cyan'},
  fadeImage: {opacity: 0.3}
}

// add a stage
let stage = new Konva.Stage({container: 'container', width: 1000, height: 500 }),
    layer = new Konva.Layer({}), // Add a layer and group to draw on
    group = new Konva.Group({clip: data.frameGroup}),
    rect = new Konva.Rect(data.frameGroup),
    image = new Konva.Image({draggable: true}),
    fadeImage = null,
    imageObj = new Image();

stage.add(layer);
layer.add(group)
group.add(rect);

rect.listening(false); // stop the frame rect intercepting events 


// Use the html image object to load the image and handle when laoded. 
imageObj.onload=function () {

  image.image(imageObj); // set the Konva image content to the html image content
  
  // compute image position so that it is initially centered in the frame
  let imagePos = getMiddlePos(data.frameGroup, data.frameGroup, {width: imageObj.width, height: imageObj.height}); 
  
  // set the Konva image attributes as needed
  image.setAttrs({
    x: imagePos.x, y: imagePos.y, width: imageObj.width, height: imageObj.height,
    
    // This function ensures the oversized image cannot be dragged beyond frame edges.
    // Is is firect by the drag event.
    dragBoundFunc: function(pos){
      var imagePos = this.getClientRect(); // get the image dimensions.
      let 
          maxPos = { // compute max x & y position allowed for image
            x: data.frameGroup.x,
            y: data.frameGroup.y
          },
          minPos = {
            x: data.frameGroup.x + data.frameGroup.width - imagePos.width,
            y: data.frameGroup.y + data.frameGroup.height - imagePos.height
          },
      
          newX = (pos.x >= maxPos.x) ? maxPos.x : pos.x, // ensure left edge not within frame
          newY = (pos.y >= maxPos.y) ? maxPos.y : pos.y; // ensure top edge not within frame
      
      newX = newX < minPos.x ? minPos.x : newX; // ensure right edge not within frame
      newY = newY < minPos.y ? minPos.y : newY; // ensure top edge not within frame
      
      fadeImage.setAttrs({x: newX, y: newY}); // apply what we computed

      // dragBoundFunc must return a value with x & y. Either return same value passed in
      // or modify the value.
      return {
        x: newX,
        y: newY
      };
    }
  })
 
  group.add(image) // add the image to the frame group
  image.moveToBottom(); // ensure the frame rect is above the image in the z-index.

  // make a clone of the image to be used as the fade image.
  fadeImage = image.clone({draggable: false, opacity: data.fadeImage.opacity});
  layer.add(fadeImage);  
  // ensure fade image is one step below the frame group. ! - in this simple demo Konva will raise 
  // a warning because group.zIndex() = 0. 
  fadeImage.zIndex(group.zIndex() - 1); 
}
imageObj.src = "https://assets.codepen.io/255591/hubble_space_image.jpg?x=1"

// simple function to get the x & y for the image to be centered in the frame
function getMiddlePos(framePos, frameSize, imageSize){
  return{
    x: framePos.x + (frameSize.width - imageSize.width)/2,
    y: framePos.y + (frameSize.height - imageSize.height)/2,
  }
}

// Toggle use of fade image to show overflowed part of image.
$('#useFadImage').on('change', function(e){
  
  if (fadeImage){
    fadeImage.visible(!fadeImage.visible());
  }
})
body {
  margin: 14px;
  padding: 10px;
  font: 12pt Verdana, Arial, sans-serif;
}
#container {
  width: 1000px;
  height: 500px;
  border: 1px solid red;
}
<p><h2>Constrain an image to the bounds of a frame</h2></p>
<p>1. Set the frame group clip region.</p>
<p>2. Set dragBounds function on the image so that it cannot escape the group.</p>
<p>Drag the image and note that it cannot me dragged such that white space in the frame would be visible.</p>
<p>
  <input type='checkbox' id='useFadImage' checked='' /><label for="useFadImage">Use fade image - shows area of image outside the frame </label>
</p>
<div id='container'  ></div>
 <p>Image from <a href="https://www.nasa.gov/multimedia/imagegallery/iotd.html">NASA Image of the day.</a></p>
 <script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js'></script>
<script src="https://unpkg.com/konva@8/konva.min.js"></script>

有一个关于here的博客条目。

相关问题