当前位置: 首页 > 知识库问答 >
问题:

javascript - 怎么用 canvas 绘制页面中 img 标签(缩放后)的图片内容?

萧越泽
2023-07-20

注意图片是使用 object-fit: cover 这种方式缩放过的
我试过下面的常规方法,但是得到的图片不太一样,因为浏览器缩放过的原因:

export const ImageToCanvas = (image: HTMLImageElement) => {  const canvas = document.createElement('canvas');  canvas.width = image.width;  canvas.height = image.height;  canvas.getContext('2d')?.drawImage(image, 0, 0);  return canvas;};export const canvasToImage = (canvas: HTMLCanvasElement) => {  const image = new Image();  image.src = canvas.toDataURL('image/png');  return image;};export const downloadImage = (image: HTMLImageElement, name: string) => {  const link = document.createElement('a');  link.download = name;  link.href = image.src;  link.click();};

image.png

共有3个答案

索寒
2023-07-20
/** * @param {{width: number, height: number}} containerSize 图片容器的宽高,单位px * @param {{width: number, height: number}} imageSize 图片宽高,单位px * @param {'fill'|'cover'|'contain'|'none'} [objectFit] * @return {[sx: number, sy: number, sWidth: number, sHeight: number, dx: number, dy: number, dWidth: number, dHeight: number]} */export function getDrawImagePosition(containerSize, imageSize, objectFit = 'fill') {  // 图片宽高比  const imageRatio = imageSize.width / imageSize.height  // 图片按容器宽高比缩放至占满整个容器  if (objectFit === 'fill') {    return [0, 0, imageSize.width, imageSize.height, 0, 0, containerSize.width, containerSize.height]  }  // 保持宽高比缩放,图片最长边占满容器,不管图片是否足以被容器包含  if (objectFit === 'contain') {    // 确定图片最长边    const longSide = imageRatio >= 1 ? 'width' : 'height'    const scaleRatio = containerSize[longSide] / imageSize[longSide]    // 最终绘制的图片尺寸    const scaleWidth = imageSize.width * scaleRatio    const scaleHeight = imageSize.height * scaleRatio    return [      0,      0,      imageSize.width,      imageSize.height,      longSide === 'width' ? 0 : (containerSize.width - scaleWidth) / 2,      longSide === 'height' ? 0 : (containerSize.height - scaleHeight) / 2,      scaleWidth,      scaleHeight    ]  }  // 保持宽高比缩放,直到恰好占满整个容器,居中显示,有可能发生裁剪,不管图片是否足以被容器包含  if (objectFit === 'cover') {    const longSide = imageRatio >= 1 ? 'width' : 'height'    const shortSide = imageRatio >= 1 ? 'height' : 'width'    let scaleRatio = containerSize[shortSide] / imageSize[shortSide]    // 最终绘制的图片尺寸    const scaleSize = {      width: imageSize.width * scaleRatio,      height: imageSize.height * scaleRatio    }    // 缩放后长边可能未占满容器,需要再次缩放    if (scaleSize[longSide] < containerSize[longSide]) {      const ratio = containerSize[longSide] / scaleSize[longSide]      scaleSize.width *= ratio      scaleSize.height *= ratio      scaleRatio = scaleSize.width / imageSize.width    }    // 原图映射到画布上的左上角相对于原图尺寸裁剪的距离    const clipWidth = (scaleSize.width - containerSize.width) / 2 / scaleRatio    const clipHeight = (scaleSize.height - containerSize.height) / 2 / scaleRatio    return [      clipWidth,      clipHeight,      imageSize.width - clipWidth,      imageSize.height - clipHeight,      0,      0,      containerSize.width,      containerSize.height    ]  }  // 保持原尺寸,居中显示,有可能发生裁剪  if (objectFit === 'none') {    // 确定是容器还是图片更大    const horizontalDiff = (containerSize.width - imageSize.width) / 2    const verticalDiff = (containerSize.height - imageSize.height) / 2    return [      horizontalDiff >= 0 ? 0 : -horizontalDiff,      verticalDiff >= 0 ? 0 : -verticalDiff,      horizontalDiff >= 0 ? imageSize.width : imageSize.width + 2 * horizontalDiff,      verticalDiff >= 0 ? imageSize.height : imageSize.height + 2 * verticalDiff,      horizontalDiff >= 0 ? horizontalDiff : 0,      verticalDiff >= 0 ? verticalDiff : 0,      horizontalDiff >= 0 ? imageSize.width : containerSize.width,      verticalDiff >= 0 ? imageSize.height : containerSize.height    ]  }  throw new Error('unknown objectFit:' + objectFit)}

返回的参数就是drawImage的后8个参数

佴博实
2023-07-20

找了一个库,可以试试

https://www.npmjs.com/package/canvas-object-fit

import Canvas from 'canvas';import {drawImage} from 'canvas-object-fit'; const [width, height] = [200, 200];const canvas = new Canvas(width, height);const context = canvas.getContext('2d');const image = new Canvas.Image();image.src = await fs.readFileAsync(`${fixturesPath}/image.jpg`);drawImage(context, image, 0, 0, canvas.width, canvas.height, {objectFit: 'cover'});const buffer = canvas.toBuffer('png');
韩鸿波
2023-07-20
export const ImageToCanvas = (image: HTMLImageElement) => {  const canvas = document.createElement('canvas');  const context = canvas.getContext('2d');  canvas.width = image.width;  canvas.height = image.height;  // 计算缩放比例和剪裁位置  const imgRatio = image.naturalWidth / image.naturalHeight;  const canvasRatio = canvas.width / canvas.height;  let sx, sy, sw, sh;  if (imgRatio > canvasRatio) {    sw = image.naturalHeight * canvasRatio;    sh = image.naturalHeight;    sx = (image.naturalWidth - sw) / 2;    sy = 0;  } else {    sw = image.naturalWidth;    sh = image.naturalWidth / canvasRatio;    sx = 0;    sy = (image.naturalHeight - sh) / 2;  }  context?.drawImage(image, sx, sy, sw, sh, 0, 0, canvas.width, canvas.height);  return canvas;};
 类似资料:
  • 问题内容: 我了解如何使用精灵,但是IMG标签不是必需的“ src”属性吗?我总是可以使用SPAN或其他标签并设置background / width / etc,但从语义上讲不会正确。 基本上,我想为IMG标签省略SRC,而只使用精灵,但是我担心HTML在技术上因此无效。谢谢。 问题答案: 关于语义正确性: 当图像具有语义时, 因此被认为是内容,请 使用IMG标签 (不带图片)和正确设置的ALT

  • 使 UIScrollView 中的图片支持手势缩放。双击图片可以放大图片,或者pinch(捏合)手势可以缩放图片。基本原理是UIScrollView中嵌套UIScrollView,然后再嵌套UIImageView,可对UIImageView进行伸缩。 [Code4App.com]

  • 就是通过F12开发者工具在网页中检查网络的那个图

  • 本文向大家介绍js+html5绘制图片到canvas的方法,包括了js+html5绘制图片到canvas的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了js+html5绘制图片到canvas的方法。分享给大家供大家参考。具体实现方法如下: 更多关于JavaScript相关内容感兴趣的读者可查看本站专题:《JavaScript动画特效与技巧汇总》《JavaScript运动效果与技巧汇总

  • 本文向大家介绍HTML5 canvas 9绘制图片实例详解,包括了HTML5 canvas 9绘制图片实例详解的使用技巧和注意事项,需要的朋友参考一下 绘制图片 Var image=new Image(); image.src=” http://img4.duitang.com/uploads/item/201406/25/20140625182321_4MTau.thumb.700_0.jpeg

  • 问题内容: 我目前有一个迷宫游戏,它绘制一个5 x 5的正方形(占用屏幕的宽度并将其均匀分割)。然后,对于每个使用x和y坐标的框,我使用drawRect绘制彩色背景。 我遇到的问题是我现在需要在同一位置绘制图像,因此需要替换当前的纯背景色填充。 这是我当前用于drawRect的代码(一些示例): 然后,我还需要为画布中的所有其他正方形实现背景图像。该背景将在其顶部绘制简单的1px黑色线条,当前代码