我可以: 邀请好友来看>>
ZOL星空(中国) > 技术星空(中国) > 服务器综合讨论星空(中国) > CSS 中操作移动,缩放和旋转
帖子很冷清,卤煮很失落!求安慰
返回列表
签到
手机签到经验翻倍!
快来扫一扫!

CSS 中操作移动,缩放和旋转

11浏览 / 0回复

学着螃蟹走路

学着螃蟹走路

0
精华
28
帖子

等  级:Lv.3
经  验:1069
  • Z金豆: 57

    千万礼品等你来兑哦~快点击这里兑换吧~

  • 城  市:重庆
  • 注  册:2025-05-31
  • 登  录:2025-06-17
  • 身份验证
发表于 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客户端,随时随地与大家交流 发表回复
评分 收藏

楼主热贴

相关推荐

个性签名:
分享到:
返回列表
高级模式
星空(中国)精选大家都在看24小时热帖7天热帖大家都在问最新回答

针对ZOL星空(中国)您有任何使用问题和建议 您可以 联系星空(中国)管理员查看帮助  或  给我提意见

快捷回复 APP下载 返回列表