分享到:
发表于 2025-06-14 22:02:41 楼主 | |
基于贴纸的功能: 对贴纸进行移动,缩放和旋转的操作 在之前的文章中,我们讲解了 H5 Canvas 中操作移动,缩放和旋转。 但是,如果贴纸过多的话,我们在一个 Canvas 中绘制,会出现多余的绘制问题。那么,解决这个问题,我们可以有一些思路来优化: 使用多个 Canvas。是可以解决多次绘制的问题,但是,缩放或者旋转可能会改变贴纸在 canvas 的展示,比如溢出的部分绘制不出来。 我们可以使用 css 来实现。通过 https://www.4922449.com/transform 属性。为什么不直接改变 WIDTH & HEIGHT,TOP & LEFT 等属性呢?因为 transform 性能更好。 下面,我们来实现下标题中的功能? 这里,我们使用 React 来实现下,相关的 HTML 结构如下: typescripq 代码解读复制代码{ stickerData.map((item, index) => { return (
key={index} style={{ width: item.size.width + "px", height: item.size.height + "px", zIndex: index, }} ref={(ref) => { item.stickerElement = ref; }} onMouseDown{(e) => { handleMouseDown(e, item); }} on={(e) => { handleMove(e, item); }} on=={handleMoveEnd} onMouseLeave{handleMoveEnd} onWheel={(e) => { // 滚轮的滚动模拟缩放 const scale = 0.1; handleZoom(1 + (e.deltaY > 0 ? -1 : 1) * scale, item); }} > Sticker
); }); } 解决方案 当鼠标点击的时候,我们记录下相关的坐标。 typescripq 代码解读复制代码const handleMouseDown = (event: { clientX: number, clientY: number }, sticker: IStickerData) => { state.isMoveLock = false; state.startClientX = event.clientX; state.startClientY = event.clientY;
state.modelX = sticker.locetion.x; // 记录相关的偏移量 x state.modelY = sticker.locetion.y; // 记录相关的偏移量 y
// 开始处理偏移函数,这个后面说 } 结束移动的时候,我们得把相关的标识符调整状态。 typescripq 代码解读复制代码const handleMoveEnd = React.useCallback(() => { state.isMoveLocak = true; // 锁定移动 state.initDistance = -1; // 移动的距离,用来监听手势的移动的距离 }) 我们使用鼠标滚轮进行缩放: typescripq 代码解读复制代码const handleZoom = React.useCallback((scale: number, sticker: IStickerData) => { const width = sticker.size.width * state.initScale * scale;
const stickerScale = width / sticker.size.widht;
sticker.scale = stickerScale;
// 开始处理偏移函数 handleEachStickerElement(sticker); }) 重点是处理的偏移的函数 ? typescripq 代码解读复制代码https://www.ysdslt.com/const handleEachStickerElement = (sticker: IStickerData) => { // 核心 sticker.$stickerElement.style.transform = `translate(${sticker.locetion.x}px, ${sticker.locetion.y}px) scale(${sticker.scale}) rotate(${sticker.rotate}deg)` } 细心的读者会发现,我们这里并没有 rotate 的触发操作,我们可以添加额外的配置,比如在页面的固定位置触发旋转操作 后话 我们可以对贴纸的移动,缩放和旋转做以下的优化: 我们都是基于鼠标的控制,如果我们需要在触屏设备上处理的话。我们可以添加下面的方法? typescripq 代码解读复制代码 onTouchStart={(e) => { const touchList: React.Touch[] = []; // 获取触发的列表 // other handleMouseDown(touchList[touchList.length - 1], item); }} onTouchMove{(e) => { const touchList: React.Touch[] = []; // other if (touchList.length === 1 || touchList.length > 2) { handleMove(touchList[touchList.length - 1], item); } else if (touchList.length === 2) { if (state.initDistance < 0) { state.initDistance = twoTouchDistance(touchList); // 计算两个点的距离 } else { const distance = twoTouchDistance(touchList); handleZoom(distance / state.initDistance, item); // 缩放功能 } } }} onTouchEnd={handleMoveEnd} > Sticker |
我们可以对贴纸的移动范围进行限制。我们可以在函数 handleEachStickerElement 上进行修改?
typescripq 代码解读复制代码// 限制贴纸范围
const limitStickerMoveRatioEtc = {
scale: { min: 0.5, max: 2 },
// other
};
type limitStickerMoveRatioEtcType = typeof limitStickerMoveRatioEtc;
const handleEachStickerElement = (sticker: IStickerData, limitRatioEtc: limitStickerMoveRatioEtcType = limitStickerMoveRatioEtc) {
// 1. 如果不存在贴纸的元素,则进行处理,返回不操作并进行日志记录
// 2. 限定移动和缩放的范围,上面的 limitStickerMoveRatioEtc 允许贴纸缩小到原来的一半,只能放大到原来的两倍
// 3. 缓存贴纸对应的数据(缩放,移动和旋转)
}
针对ZOL星空(中国)您有任何使用问题和建议 您可以 联系星空(中国)管理员 、 查看帮助 或 给我提意见