返回

图像不变形缩放显示的meetOrSlice算法详解

前端

1. SVG中的viewport, viewBox和preserveAspectRatio

1.1 SVG中的viewport

SVG中的viewport是指SVG图像的显示区域,它是一个矩形区域,可以通过元素的width和height属性来指定。viewport的单位是像素(px)。

1.2 SVG中的viewBox

SVG中的viewBox是指SVG图像的实际大小,它是一个矩形区域,可以通过元素的viewBox属性来指定。viewBox的单位是用户单位(user units)。

1.3 SVG中的preserveAspectRatio

SVG中的preserveAspectRatio属性是指SVG图像的缩放方式,它可以通过元素的preserveAspectRatio属性来指定。preserveAspectRatio属性有以下几个值:

  • none :不缩放图像。
  • meet :将图像缩放至刚好填满viewport,但不裁剪图像。
  • slice :将图像缩放至刚好填满viewport,并裁剪图像。
  • xMinYMin :将图像缩放至刚好填满viewport,但图像的最小x坐标和最小y坐标必须与viewport的最小x坐标和最小y坐标对齐。
  • xMidYMin :将图像缩放至刚好填满viewport,但图像的中间x坐标和最小y坐标必须与viewport的中间x坐标和最小y坐标对齐。
  • xMaxYMin :将图像缩放至刚好填满viewport,但图像的最大x坐标和最小y坐标必须与viewport的最大x坐标和最小y坐标对齐。
  • xMinYMid :将图像缩放至刚好填满viewport,但图像的最小x坐标和中间y坐标必须与viewport的最小x坐标和中间y坐标对齐。
  • xMidYMid :将图像缩放至刚好填满viewport,但图像的中间x坐标和中间y坐标必须与viewport的中间x坐标和中间y坐标对齐。
  • xMaxYMid :将图像缩放至刚好填满viewport,但图像的最大x坐标和中间y坐标必须与viewport的最大x坐标和中间y坐标对齐。
  • xMinYMax :将图像缩放至刚好填满viewport,但图像的最小x坐标和最大y坐标必须与viewport的最小x坐标和最大y坐标对齐。
  • xMidYMax :将图像缩放至刚好填满viewport,但图像的中间x坐标和最大y坐标必须与viewport的中间x坐标和最大y坐标对齐。
  • xMaxYMax :将图像缩放至刚好填满viewport,但图像的最大x坐标和最大y坐标必须与viewport的最大x坐标和最大y坐标对齐。

2. preserveAspectRatio中meetOrSlice算法

在preserveAspectRatio属性中,meetOrSlice算法是将图像缩放至刚好填满viewport,但不会裁剪图像。如果图像的宽高比与viewport的宽高比不同,则图像将被拉伸或压缩以适应viewport。

meetOrSlice算法的实现步骤如下:

  1. 计算图像的宽高比和viewport的宽高比。
  2. 如果图像的宽高比大于viewport的宽高比,则将图像的宽度缩放至viewport的宽度,并保持图像的高度不变。
  3. 如果图像的宽高比小于viewport的宽高比,则将图像的高度缩放至viewport的高度,并保持图像的宽度不变。
  4. 将图像平移至viewport的中心。

3. 代码实现

function meetOrSlice(svg, viewport, viewBox) {
  // 计算图像的宽高比和viewport的宽高比。
  const imageAspectRatio = viewBox.width / viewBox.height;
  const viewportAspectRatio = viewport.width / viewport.height;

  // 如果图像的宽高比大于viewport的宽高比,则将图像的宽度缩放至viewport的宽度,并保持图像的高度不变。
  if (imageAspectRatio > viewportAspectRatio) {
    const scale = viewport.width / viewBox.width;
    svg.setAttribute("width", viewport.width);
    svg.setAttribute("height", viewBox.height * scale);
  }

  // 如果图像的宽高比小于viewport的宽高比,则将图像的高度缩放至viewport的高度,并保持图像的宽度不变。
  else {
    const scale = viewport.height / viewBox.height;
    svg.setAttribute("width", viewBox.width * scale);
    svg.setAttribute("height", viewport.height);
  }

  // 将图像平移至viewport的中心。
  svg.setAttribute("transform", "translate(" + (viewport.width - svg.width) / 2 + "," + (viewport.height - svg.height) / 2 + ")");
}