在 Konva.js 中模拟图像的“object-fit:contain”

问题描述 投票:0回答:1

我正在尝试制作可调整大小的图像,其内容完全适合矩形。我找到了如何模拟 object-fit: cover 的解决方案,但我需要包含。 我做了一些解决方案:

const width = size.width;
const height = size.height;

var scalex = image.width / width;
var scaley = image.height / height;
var scale = Math.max(scalex, scaley);

return {
  cropWidth: width * scale,
  cropHeight: height * scale,
};

但它没有将图像居中

有什么想法如何使其居中吗?

canvas html5-canvas konvajs react-konva konva
1个回答
0
投票

仅使用

Konva.Image
和裁剪是无法做到这一点的。 Konva 可以通过裁剪来剪切内容。但它无法用空白空间来渲染它。对于这种情况,我们可以使用外部画布。

// Create a new Konva stage with the dimensions of the window
const stage = new Konva.Stage({
  container: 'container',
  width: window.innerWidth,
  height: window.innerHeight
});

// Create a new layer to hold the image and transformer
const layer = new Konva.Layer();
// Add the layer to the stage
stage.add(layer);

// Define a function to fit and center an image within a canvas element
function fitContain({canvas, image, canvasWidth, canvasHeight}) {
    // Get the 2D rendering context for the canvas
    const ctx = canvas.getContext('2d');
    
    // Set the dimensions of the canvas
    canvas.width = canvasWidth;
    canvas.height = canvasHeight;
    
    // Calculate the aspect ratios of the image and the canvas
    const imageAspect = image.naturalWidth / image.naturalHeight;
    const canvasAspect = canvasWidth / canvasHeight;
    
    let renderWidth, renderHeight;
    
    // Determine the dimensions to render the image at to maintain aspect ratio
    if (imageAspect > canvasAspect) {
        renderWidth = canvasWidth;
        renderHeight = canvasWidth / imageAspect;
    } else {
        renderWidth = canvasHeight * imageAspect;
        renderHeight = canvasHeight;
    }
    
    // Calculate the position to center the image in the canvas
    const offsetX = (canvasWidth - renderWidth) / 2;
    const offsetY = (canvasHeight - renderHeight) / 2;
    
    // Draw the image on the canvas at the calculated dimensions and position
    ctx.drawImage(image, offsetX, offsetY, renderWidth, renderHeight);
    
    // Return the canvas element
    return canvas;
}

// Create a new image element
const image = new window.Image();
// Set the source of the image
image.src = 'https://i.imgur.com/ktWThtZ.png';
// Define an onload handler to execute once the image has loaded
image.onload = () => {
  // Create a new canvas element
  const canvas = document.createElement('canvas');
  
  // Create a new Konva Image to hold the canvas
  const img = new Konva.Image({
    image: canvas,
    x: 50,
    y: 60,
    width: 200,
    height: 100,
    draggable: true
  });
  // Add the Konva Image to the layer
  layer.add(img);
  // Call fitContain to fit and center the image in the canvas
  fitContain({canvas, image, canvasWidth: img.width(), canvasHeight: img.height() });
  
  // Create a new transformer to allow the Konva Image to be resized
  const tr = new Konva.Transformer({
    flipEnabled: false,
    nodes: [img]
  });
  // Add the transformer to the layer
  layer.add(tr);
  
  // Define a transform event handler to update the canvas when the Konva Image is resized
  img.on('transform', () => {
    // Update the dimensions of the Konva Image to reflect the scaling transformation
    img.setAttrs({
      width: img.width() * img.scaleX(),
      height: img.height() * img.scaleY(),
      scaleX: 1,
      scaleY: 1
    });
    // Call fitContain to fit and center the image in the canvas again
    fitContain({canvas, image, canvasWidth: img.width(), canvasHeight: img.height() });
  })
}
  <script src="https://unpkg.com/konva@^9/konva.min.js"></script>
    <div id="container"></div>

© www.soinside.com 2019 - 2024. All rights reserved.