javascript - 如何通过放大和缩小来修改图像?
问题描述
我有一个类似画廊的组件,重要的部分是:
<Gallery>
<Header>
<img src={galleryIcon} alt='Galley icon' />
<h1>My Gallery</h1>
</Header>
<Images isImage={custom.length > 0}>
{custom.length > 0 &&
custom.map((c, i) => (
<img
id={`custom${i}`}
key={`custom${i}`}
src={c.img}
alt='brick'
onClick={() => (setEdit((prev) => !prev), setActual(c))}
/>
))}
<div className='add'>
<button onClick={() => setGallery((prev) => !prev)}>
<img src={add} alt='Add icon' />
</button>
<p>Click to add a brick from our collections!</p>
</div>
</Images>
</Gallery>
每个图像都有这种风格:
img {
box-sizing: border-box;
height: 28vh;
width: 28vh;
margin-right: 1.5rem;
cursor: pointer;
}
此外,一旦用户输入新图像,我会使用以下功能调整大小以不破坏比例:
export function resizeImage(
file: File | Blob,
maxWidth: number,
maxHeight: number,
scale = 1
): Promise<Blob> {
return new Promise<Blob>((fulfill, reject) => {
const image = new Image();
image.src = URL.createObjectURL(file);
image.onload = () => {
URL.revokeObjectURL(image.src);
const width = image.width;
const height = image.height;
if (width <= maxWidth && height <= maxHeight) {
fulfill(file);
}
let newWidth = 0;
let newHeight = 0;
if (scale !== 1) {
newWidth = (width * scale) / maxWidth;
newHeight = (height * scale) / maxHeight;
} else if (width > height) {
newHeight = height * (maxWidth / width);
newWidth = maxWidth;
} else {
newWidth = width * (maxHeight / height);
newHeight = maxHeight;
}
console.log(newWidth, newHeight);
const canvas = document.createElement('canvas');
canvas.width = newWidth;
canvas.height = newHeight;
const context = canvas.getContext('2d');
context?.drawImage(image, 0, 0, newWidth, newHeight);
canvas.toBlob((blob) => blob && fulfill(blob), file.type);
};
image.onerror = reject;
});
}
最后,调整大小组件:
const Resize: React.FC<Props> = ({ actual, setResize, setCustom, custom }) => {
let stats: Stats = {} as Stats;
const getStats = useCallback((): Stats => stats, []);
const updateStats = useCallback(
(newStats: Stats): Stats => (stats = newStats),
[]
);
const getResizedCustom = useCallback(
async (copy: Custom): Promise<Custom> => {
const actualWidth = window.innerWidth;
const actualHeight = window.innerHeight;
const maxWidth = actualWidth < 1152 ? 180 : 360;
const maxHeight = actualHeight < 800 ? 180 : 360;
const newBlob = await resizeImage(
copy.blob,
maxWidth,
maxHeight,
getStats().scale
);
return {
blob: newBlob,
img: URL.createObjectURL(newBlob),
id: copy.id,
type: 'custom',
price: copy.price,
amount: copy.amount,
};
},
[stats]
);
const updateActual = useCallback(async () => {
// remove actual
const newCustomArr = [...custom];
const customCopy = newCustomArr.splice(newCustomArr.indexOf(actual), 1)[0];
const newCustom = await getResizedCustom(customCopy);
console.log(customCopy);
console.log(newCustom);
setCustom([...newCustomArr, newCustom]);
}, [actual, custom, setCustom, getResizedCustom]);
return (
<Container>
<Header>
<h1>ADJUST YOUR BRICK</h1>
<img
src={close}
alt='close icon'
onClick={() => setResize((prev) => !prev)}
/>
</Header>
<Main>
<h2>Pinch and zoom</h2>
<TransformWrapper onZoomChange={updateStats}>
<TransformComponent>
<img src={actual.img} alt='brick' />
</TransformComponent>
</TransformWrapper>
<button
onClick={async () => (
await updateActual(), setResize((prev) => !prev)
)}
>
DONE
</button>
</Main>
</Container>
);
};
我还使用react-zoom-pan-pinch来放大和缩小图像。我的问题是:如何根据 TransformWrapper 组件的 onZoomChange 函数提供的比例调整 DOM 上的图像大小?那可能吗?有一种更好且不那么“hacky”的方法可以根据缩放比例在 DOM 上调整图像的大小?
我会尽快提供最低限度的回购,但现在,这里是完整的回购:https ://github.com/Mdsp9070/brickart/tree/dev
解决方案
这肯定是可能的,但是您需要将更多道具传递给drawImage
. 查看文档。它还有四个您没有使用的可选参数。如果您只使用前四个,则包括整个图像。当使用所有八个道具时,前四个是指要使用原始图像的哪个部分(裁剪),而接下来的四个指定将图像选择放在画布上的哪个位置。
您需要进行一些数学运算和一些事件跟踪,以根据缩放中心和比例计算源矩形。
推荐阅读
- flutter - 无法使用 just_audio 在 Flutter Android 中播放声音
- java - Android Java 随机数学除法一直显示“除以零”
- statistics - 如何确定 Gumbel 分布的均值和 Cov?
- delphi - OleVariant 和 SafeSysFreeString
- spring-boot - SpringBoot REST 生成pdf
- c# - 从 opencv mat/Array 到 OnnxRuntime 张量的转换优化?
- django - get() 返回了多个成员 -- 它返回了 11
- python - 训练标准 UNet 模型和进行 keras data_augmentation 时输入的尺寸不匹配?
- php - 如何启动具有依赖关系的服务而不在方法参数中声明它?
- reactjs - 在 React 受控组件中修改用户输入值