如何在前端项目中对页面元素进行放大缩小操作?

5,291 阅读8分钟

「我正在参与掘金创作者训练营第4期,点击了解活动详情,一起学习吧!」

前言

掘金创作者训练营安排了两篇作业,上一篇文章为了您更好的体验,本文章聊聊如何仅支持谷歌浏览器访问查看页面?各位掘友可以去瞅瞅。现在我再来写一篇,把这个作业给完成了,做啥事还是得有始有终,常言道:有始有终,方为人道。有始有终,言而有信

哈哈哈,一下就把逼格整高了,但不影响我们要聊的主题,那就是如何在项目中对页面进行缩放操作?这个操作还是挺常见的,可以码住收藏起来^_^

需求背景

背景就是该页面是嵌入CAD软件进行查看编辑操作的,接触过CAD软件的掘友应该知道里面的字体字号都很细小不便于查看的,故CAD就提供了鼠标缩放事件让界面可以放大缩小进行操作查看,然而我们的该页面既然嵌入CAD,那也被要求需要具备像CAD软件那样的缩放操作功能,所以也就有了今天要聊的话题。

从背景应该可以知道需求的点滴了吧。那真正的需求就是:使用H5开发一个页面,可以查看编辑项目信息,并且支持缩放页面操作。反正一句话需求很简单,但是真实需求一二十句话也不止,直接老规矩上设计图便于理解,如下图所示:

微信截图_20220218154204.png

这下应该知道我要聊的和要做的了吧。如果眼尖的掘友应该发现,我在如何在项目中引入外部字体并使用?这篇文章用到的截图就来自此需求设计图。之前是管中窥豹,只见一斑,现在可以说是一目了然了。

上线效果图如下(不便使用CAD录制gif图,CAD含私密信息不宜公开):

test4.gif

思考

其实针对上面一句话需求可思考的主要问题就只有:如何实现缩放页面功能?其他的就没有必要延伸思考了,毕竟此文主要聊的也就是如何实现缩放页面而已。好,那就直奔主题,见下面叙述→

开发

针对上面提出的思考,去找寻解决办法可知:想实现页面的缩放,那还得通过控制样式从而达到控制页面进行放大缩小效果。故根据积累的知识可以得到解决问题的核心就是transformtransform-origin

transform属性向元素应用2D或3D转换。该属性允许我们对元素进行旋转、缩放、移动或倾斜

transform相关属性如下表所示:

描述
none定义不进行转换。
matrix(n,n,n,n,n,n)定义2D转换,使用六个值的矩阵。
matrix3d(n,n,n,n,n,n,n,n,n,n,n,n,n,n,n,n)定义3D转换,使用 16个值的4x4矩阵。
translate(x,y)定义2D转换。
translate3d(x,y,z)定义3D转换。
translateX(x)定义转换,只是用X轴的值。
translateY(y)定义转换,只是用Y轴的值。
translateZ(z)定义3D转换,只是用Z轴的值。
scale(x,y)定义2D缩放转换。
scale3d(x,y,z)定义3D缩放转换。
scaleX(x)通过设置X轴的值来定义缩放转换。
scaleY(y)通过设置Y轴的值来定义缩放转换。
scaleZ(z)通过设置Z轴的值来定义3D缩放转换。
rotate(angle)定义2D旋转,在参数中规定角度。
rotate3d(x,y,z,angle)定义3D旋转。
rotateX(angle)定义沿着X轴的3D旋转。
rotateY(angle)定义沿着Y轴的3D旋转。
rotateZ(angle)定义沿着Z轴的3D旋转。
skew(x-angle,y-angle)定义沿着X和Y轴的2D倾斜转换。
skewX(angle)定义沿着X轴的2D倾斜转换。
skewY(angle)定义沿着Y轴的2D倾斜转换。
perspective(n)为3D转换元素定义透视视图。

MDN提供了transform的相关示例体验,可以点击链接前往体验。

transform-origin属性允许改变被转换元素的位置。

描述
x-axis定义视图被置于X轴的何处。可能的值:top、left、center、right、length%
y-axis定义视图被置于Y轴的何处。可能的值:top、left、center、right、length%
z-axis定义视图被置于Z轴的何处。可能的值:length

MDN提供了transform-origin的相关示例体验,可以点击链接前往体验。

从上面的介绍可以知道,实现上面的需求需要使用transformscale()属性和transform-origin进行搭配使用,具体实现如下(代码使用React技术栈):

页面布局:

微信截图_20220218171606.png

样式代码:

.bit-right-container {
    display: flex;
    justify-content: center;
    align-items: center;
    transform-origin: top; // 重要
}

.bit-wrap-options {
    position: fixed;
    top: 0;
    right: 16px;

    .bit-zoom-box {
        display: flex;
        justify-content: center;
        align-items: center;
        width: 32px;
        height: 32px;
        margin-top: 16px;
        background: #FFFFFF;
        box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.16);
        border-radius: 50%;
        color: #313C42;
    }

    .bit-zoom-box:hover {
        background: linear-gradient(180deg, #FFFFFF 0%, #EEEEEE 100%);
        box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.16);
    }

    .active {
        background: linear-gradient(180deg, #F5F5F5 0%, #EEEEEE 100%);
        box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.16);
    }
}

逻辑代码:

// 定义缩放Icon集合常量
const ZoomIcons: any[] = [
    {key: 'zoomOut', label: '缩小', value: <ZoomOutOutlined className="f14" />},
    {key: 'zoomIn', label: '放大', value: <ZoomInOutlined className="f14" />},
    {key: 'zoomReload', label: '还原', value: <ReloadOutlined className="f14" />}
]

// 缩放比例,默认为0.9
const [zoomScale, setZoomScale] = useState<number>(0.9);
// 缩放图标
const [zoomIcon, setZoomIcon] = useState<string>('');
/**
 * 操作放大缩小页面函数
 * @param key
 */
const handleZoom = (key: string) => {
    setZoomIcon(key);
    if (key === 'zoomOut' && zoomScale <= 0.1) {
        setZoomScale(0.1);
        return;
    }
    if (key === 'zoomOut' && zoomScale > 0.1) {
        setZoomScale(zoomScale - 0.1);
        return;
    }
    if (key === 'zoomIn') {
        setZoomScale(zoomScale + 0.1);
        return;
    }
    setZoomScale(0.9);
}

从上述代码可以看到,我是用React特性hooks相关语法创建的页面文件,然后定义一个Icons集合来用于渲染界面上的缩小、放大和还原按钮;然后创建了两个statezoomScalezoomIconzoomIcon用于识别用户点击的是哪一个操作按钮,然后加上对应的样式效果;zoomScale则是用于控制缩放页面容器的缩放比例;再者handleZoom()函数用于控制操作逻辑,只不过要注意的是:当比例值为0时页面元素宽高都为0了;而为负数时页面则被旋转了180度导致页面出现错误的渲染效果,所以增加了一个逻辑就是当比例值小于等于0.1时就让比例值为0.1,保证页面还存在不消失。

其实当比例为负数的时候还可以通过transform: scale(-1) ratate(180deg);将页面即可旋转回原样,但是为了这些不必要的麻烦,所以就增加判断小于等于0.1的情况,保证不会一直减小到0和负数;还有就是如果设置transform-origin: center;,当不断放大时,页面就不能滚动查看了,所以为了避免不能滚动所以我们设置了 元素改变的原点为center top,即transform-origin: top;,这样就能保证页面放大了之后也可以上下滚动查看了,如下图所示:

test2.gif

至此,项目中如何缩放页面的需求就聊完了,其实只要了解相关的API该需求就会变得简单,最怕的就是完事开头难,所以平时要多积累开发经验,这样才不会让自己在以后的开发中显得被动。最后掘金创作者训练营的作业也就完成了,希望后续还有类似的活动安排,这对我们的创作有相当大的帮助,感谢感谢👍

往期精彩文章

后语

伙伴们,如果觉得本文对你有些许帮助,点个👍或者➕个关注在走呗^_^ 。另外如果本文章有问题或有不理解的部分,欢迎大家在评论区评论指出,我们一起讨论共勉。