【问题标题】:Load and center an image of unknown dimensions keeping aspect ratio and padding加载和居中未知尺寸的图像,保持纵横比和填充
【发布时间】:2018-10-12 15:36:05
【问题描述】:

我正在尝试将通过 KonvasJS 动态添加到画布的图像直接居中。

这是小提琴:

http://jsfiddle.net/71Lw0bk8/7/

我已经弄清楚了代码,但它没有使用 Konva,这是在没有库的情况下尝试这样做,并且它运行良好。

function addImage(imgUrl) {

    const img = new Image();

    img.onload = function () {
        var padding = 20;
        while (img.width + padding > canvas.width || img.height + padding > canvas.height) {
            if (img.width + padding > canvas.width) {
                let newWidth = canvas.width - (padding * 2);
                img.height = Math.round((img.height / img.width) * newWidth);
                img.width = newWidth;
            }
            else if (img.height + padding > canvas.height) {
                let newHeight = canvas.height - (padding * 2);
                img.width = Math.round((img.width / img.height) * newHeight);
                img.height = newHeight;
            }
        }
        ctx.drawImage(img, canvas.width / 2 - img.width / 2, canvas.height / 2 - img.height / 2, img.width, img.height);
    };
    img.src = imgUrl;
}

我只是不确定如何将其转换为此处:

var uploadedImage = new Konva.Image({
    x: stage.getWidth() / 2,
    y: stage.getHeight() / 2,
    width: 200,
    height: 200,
    ...

我该怎么做?

【问题讨论】:

  • 我认出了那张图片 - 这是 konvajs 版本的带有变换的图像拖动图像吗?欢迎回来!
  • 是的,Vanquided,谢谢你的建议,它比 Fabric 更容易理解,虽然我还是有点迷茫!哈
  • 你创建一个标准的 js 图像并分配它的 src。然后在 onload 事件中创建 Konva.Image。此处的示例konvajs.github.io/docs/shapes/Image.html - 因此它与您在上面的纯 JS 代码示例中的内容非常相似,但将 ctx.drawImage() 替换为 Konva.Image 的创建。并且不要忘记 layer.draw()。
  • @VanquiishedWombat 介意做一个例子小提琴吗?我完全迷路了。

标签: javascript jquery html canvas konvajs


【解决方案1】:

技术与普通 JS 相同。使用 JS 图像的 onload 事件来决定要显示的内容和大小等。一旦完成所有这些,居中的工作就是一个非常标准的矩形逻辑。请参阅下面的 centerRectShape() 函数。

编辑:添加更多动态图像大小以丰富 sn-p。

编辑:之前更改的图像源已移动。

// the x,y position of a rect shape is in fact the top left corner, so to 
// correcty centre we should consider width and height in the mix.
// Konva.Rect and Konva.Image shapes both have x, y being topleft. 
function centreRectShape(shape){
  shape.x( ( stage.getWidth() - shape.getWidth() ) / 2);
  shape.y( ( stage.getHeight() - shape.getHeight() ) / 2);
}

// Set up the stage
var stage = new Konva.Stage({
  container: 'canvas-container',
  width: 650,
  height: 300
});

// We draw on layers so create one
var layer = new Konva.Layer();
stage.add(layer);

var bgRect = new Konva.Rect({width: stage.getWidth(), height: stage.getHeight(), fill: 'gold', opacity: 0.1});
layer.add(bgRect);

// we will be uploading an image so make somewhere for it to be displayed later
var uploadedImage = new Konva.Image({
    x: stage.getWidth() / 2,
    y: stage.getHeight() / 2,
    width: 200, 
    height: 200,
    stroke: 'red',
    strokeWidth: 10,
    draggable: false
});

// Always have to add shapes to a layer.
layer.add(uploadedImage);

// use a standard plain old JS image to do the pull of the image from src
imgObj = new Image();

// we harness the onload event to know when to update the canvas image
imgObj.onload = function() {

  uploadedImage.image(imgObj);  // give the image to the cannvas image object.
  
  // since this is a dynamic image upload we want to resize the canvas image object to get 
  // a pleasing effect.
  var padding = 20;
  var w = imgObj.width;  
  var h = imgObj.height;
  
  // get the aperture we need to fit by taking padding off the stage size.
  var targetW = stage.getWidth() - (2 * padding);
  var targetH = stage.getHeight() - (2 * padding);

  // compute the ratios of image dimensions to aperture dimensions 
  var widthFit =  targetW / w;
  var heightFit = targetH / h;
  
  // compute a scale for best fit and apply it
  var scale = (widthFit > heightFit) ? heightFit : widthFit  ;
    
  w = parseInt(w * scale, 10);
  h = parseInt(h * scale, 10);
  
  uploadedImage.size({
    width: w,
    height: h
  });
   
  // Finally position the canvas image object centered.
  centreRectShape(uploadedImage); 
  
  layer.draw(); // My favourite thing to forget.
}

// to start the image load give the object a new src. 
imgObj.src = 'https://via.placeholder.com/600x280/0000FF/FFFFFF.png?text=Wombats are awsome';
html, * {
  margin: 0;
  padding: 0;
}

body {
  background: #eee;
}

#canvas-container {
  background: #fff;
  border-radius: 3px;
  border: 1px solid #d8d8d8;
  width: 650px;
  margin: 0 auto;
  margin-top: 20px;
  box-shadow: 0 3px 5px rgba(0, 0, 0, .2);
}

.stickers {
  padding: 10px 5px;
}

.stickers > img {
  margin-right: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/konva/2.4.1/konva.min.js"></script>

<div id="canvas-container"></div>

【讨论】:

  • 谢谢!我想我应该更多地解释图像不会是 200。它将是不同的尺寸,特别是如果它是肖像或风景照片。我如何才能将动态尺寸用于此?
  • 加上填充,这样图像就不会溢出画布。
  • @kinx 查看修改后的 sn-p。尺寸调整代码与普通 JS 所做的相同,即对加载图像的尺寸做出反应。
  • 你是最棒的@Vanquiished Wombat!
  • @VanquiishedWombat 的解释在 cmets 中非常清楚。非常感谢你 :)
猜你喜欢
  • 2012-08-23
  • 1970-01-01
  • 2015-07-25
  • 1970-01-01
  • 1970-01-01
  • 2016-05-16
  • 1970-01-01
  • 2012-02-24
  • 2016-02-15
相关资源
最近更新 更多