You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Konva图层节点适配视口:居中后缩放算法实现问询

解决Konva Stage视口适配:完整显示所有图形并居中

嘿,我刚好处理过类似的Konva视口适配需求,给你分享个靠谱的实现思路,帮你搞定缩放比例的问题!

核心思路

要让所有图形不被裁切,关键是先算出所有内容的整体边界框,再根据视口尺寸计算出合适的缩放比例,最后结合居中逻辑调整舞台的位置和缩放。

步骤1:计算所有图形的联合边界框

首先我们需要获取所有可见图形的整体范围,这样才能知道内容的实际大小:

// 获取舞台上所有可见的图形节点
const visibleShapes = stage.find('Shape').filter(shape => shape.visible());
if (visibleShapes.length === 0) return; // 没有图形时直接返回

// 初始化边界值
let minX = Infinity, minY = Infinity;
let maxX = -Infinity, maxY = -Infinity;

// 遍历所有图形,计算联合边界
visibleShapes.forEach(shape => {
  // getClientRect()会自动考虑节点的缩放、旋转等变换,返回相对于舞台的边界
  const rect = shape.getClientRect();
  minX = Math.min(minX, rect.x);
  minY = Math.min(minY, rect.y);
  maxX = Math.max(maxX, rect.x + rect.width);
  maxY = Math.max(maxY, rect.y + rect.height);
});

// 计算内容的实际宽高
const contentWidth = maxX - minX;
const contentHeight = maxY - minY;

步骤2:计算适配视口的缩放比例

我们需要取视口与内容宽高比中较小的那个值,这样能保证内容完整放进视口,不会出现裁切。如果希望内容和视口之间留一点边距,可以给比例乘以一个小于1的系数(比如0.95):

// 获取视口(舞台容器)的实际尺寸
const viewportWidth = stage.container().offsetWidth;
const viewportHeight = stage.container().offsetHeight;

// 计算宽、高方向的适配比例
const scaleX = viewportWidth / contentWidth;
const scaleY = viewportHeight / contentHeight;

// 取较小的比例,同时限制最大缩放比例为1(避免内容比视口小时被放大)
const fitScale = Math.min(scaleX, scaleY, 1) * 0.95;

步骤3:设置舞台的缩放与居中位置

结合内容中心点和视口中心点,调整舞台的位置,确保缩放后的内容完全居中:

// 计算内容的中心点坐标
const contentCenterX = minX + contentWidth / 2;
const contentCenterY = minY + contentHeight / 2;

// 计算视口的中心点坐标
const viewportCenterX = viewportWidth / 2;
const viewportCenterY = viewportHeight / 2;

// 应用缩放和位置调整
stage.scale({ x: fitScale, y: fitScale });
stage.position({
  x: viewportCenterX - contentCenterX * fitScale,
  y: viewportCenterY - contentCenterY * fitScale
});

// 刷新舞台
stage.draw();

额外注意事项

  • 如果你的画布包含GroupLayerfind('Shape')会自动遍历所有子节点,无需额外处理;
  • getClientRect()方法已经考虑了节点的scalerotationposition等变换,无需手动计算;
  • 如果不需要限制最大缩放比例(允许内容比视口小时放大填满),可以去掉Math.min里的1参数。

这样调整后,你的Konva舞台就能自动适配视口,让所有图形完整显示且居中啦!

内容的提问来源于stack exchange,提问作者Tyler Churchill

火山引擎 最新活动