「我正在参与掘金创作者训练营第4期,点击了解活动详情,一起学习吧!」
前言
掘金创作者训练营安排了两篇作业,上一篇文章为了您更好的体验,本文章聊聊如何仅支持谷歌浏览器访问查看页面?各位掘友可以去瞅瞅。现在我再来写一篇,把这个作业给完成了,做啥事还是得有始有终,常言道:有始有终,方为人道。有始有终,言而有信。
哈哈哈,一下就把逼格整高了,但不影响我们要聊的主题,那就是如何在项目中对页面进行缩放操作?这个操作还是挺常见的,可以码住收藏起来^_^
需求背景
背景就是该页面是嵌入CAD软件进行查看编辑操作的,接触过CAD软件的掘友应该知道里面的字体字号都很细小不便于查看的,故CAD就提供了鼠标缩放事件让界面可以放大缩小进行操作查看,然而我们的该页面既然嵌入CAD,那也被要求需要具备像CAD软件那样的缩放操作功能,所以也就有了今天要聊的话题。
从背景应该可以知道需求的点滴了吧。那真正的需求就是:使用H5开发一个页面,可以查看编辑项目信息,并且支持缩放页面操作。反正一句话需求很简单,但是真实需求一二十句话也不止,直接老规矩上设计图便于理解,如下图所示:
这下应该知道我要聊的和要做的了吧。如果眼尖的掘友应该发现,我在如何在项目中引入外部字体并使用?这篇文章用到的截图就来自此需求设计图。之前是管中窥豹,只见一斑,现在可以说是一目了然了。
上线效果图如下(不便使用CAD录制gif图,CAD含私密信息不宜公开):
思考
其实针对上面一句话需求可思考的主要问题就只有:如何实现缩放页面功能?其他的就没有必要延伸思考了,毕竟此文主要聊的也就是如何实现缩放页面而已。好,那就直奔主题,见下面叙述→
开发
针对上面提出的思考,去找寻解决办法可知:想实现页面的缩放,那还得通过控制样式从而达到控制页面进行放大缩小效果。故根据积累的知识可以得到解决问题的核心就是transform和transform-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的相关示例体验,可以点击链接前往体验。
从上面的介绍可以知道,实现上面的需求需要使用transform的scale()属性和transform-origin进行搭配使用,具体实现如下(代码使用React技术栈):
页面布局:
样式代码:
.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集合来用于渲染界面上的缩小、放大和还原按钮;然后创建了两个state:zoomScale和zoomIcon,zoomIcon用于识别用户点击的是哪一个操作按钮,然后加上对应的样式效果;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;,这样就能保证页面放大了之后也可以上下滚动查看了,如下图所示:
至此,项目中如何缩放页面的需求就聊完了,其实只要了解相关的API该需求就会变得简单,最怕的就是完事开头难,所以平时要多积累开发经验,这样才不会让自己在以后的开发中显得被动。最后掘金创作者训练营的作业也就完成了,希望后续还有类似的活动安排,这对我们的创作有相当大的帮助,感谢感谢👍
往期精彩文章
- 为了您更好的体验,本文章聊聊如何仅支持谷歌浏览器访问查看页面?
- 聊聊如何在React项目中使用Antd的Table组件实现Echarts的热力图效果?
- 如何在项目中引入外部字体并使用?
- 如何在React项目中使用高德地图插件并封装弹窗组件呢?
- 数据可视化-如何在React项目中使用Echarts插件并封装图表组件?
- 快来看看我是如何更改Antd中DatePicker周选择器默认设置的?
- 如何封装Vue水印组件和 React中如何使用水印组件?
- 最强富文本编辑器?TinyMCE系列文章【3】
- 最强富文本编辑器?TinyMCE系列文章【2】
- 最强富文本编辑器?TinyMCE系列文章【1】
- 在React项目中实现仿饿了么Checkbox多选按钮样式的效果组件
- 2022第一次更文:前端项目实战中的3种Progress进度条效果
- 2022年前端技术趋势:你不进来看看,怎么赚它一个小目标?
- 假如古代有程序员写总结,大概就是这样吧 | 2021年终总结
后语
伙伴们,如果觉得本文对你有些许帮助,点个👍或者➕个关注在走呗^_^ 。另外如果本文章有问题或有不理解的部分,欢迎大家在评论区评论指出,我们一起讨论共勉。