这篇文章发布于 2022年11月20日,星期日,19:10,归类于 JS实例。 阅读 13047 次, 今日 4 次 6 条评论
by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=10611 鑫空间-鑫生活
本文欢迎分享与聚合,全文转载就不必了,尊重版权,圈子就这么大,若急用可以联系授权。
欢迎光临,效果先行:
上为视频,不动轻戳。
如果您是使用PC机器阅读的本文,也可以点击此页面实际操作感受下。
如果查看源码,会发现只有个 img 元素,并无任何其他辅助:
如何实现的呢?下面是正文↓
一、背景之工作需求
最近在做富文本编辑器相关的需求,其中就有上传图片后需要对图片进行拉伸的需求。
比方说下图所示的交互就是腾讯文档中的图片缩放效果:
我以前也多次实现过(图片上传,头像上传,以及一些工具类产品),不过实现方式都是 <img>
元素外面包裹个 DIV,然后定位一些方框框,然后再去拉伸。
如果是非编辑器产品,这么实现并没有多大的问题。
但是如果是需要实时编辑的产品,IMG外面还有其他标签,势必会影响很多编辑操作。当然,还有方法就是JS定位,拖拽层覆盖在图像上,从技术成本上讲,也是一个不错的实现,但如果页面发生了滚动,或者拖拽很快,拖拽的小方块就有可能跟不上(具体要看你的实现)。
所以我就在想,以如今的Web能力,有没有可能无需任何其他借助,单单就一个 <img>
标签,就实现图像的拉伸效果呢?
我脑中迅速遍历了下我所知的技术点,貌似理论上可行。
然后……
二、并没有预想的顺利
原本的设计稿是这样的:
四个角四个圆圈圈,比较简洁,凡是这种在元素边框(不包括边角)包含规则图形(没有图形也是一种规律)的效果,一定是使用CSS border-image
属性。
CSS border-image
属性可以无限外扩,不占据布局空间,非常强,具体语法参见 《CSS新世界》对应章节,高级应用参见“被低估的border-image属性”一文。
然而,border-image
属性想要使用顺畅,需要设计师的素材配合,需要按照九宫格布局进行设计,下面就是我在 PS 中给设计师绘制的结构示意:
随后设计师按照此示意结构将图形矢量化(变成 SVG 文件),我再去实现,结果发现了一个棘手的问题,什么问题呢?
直接看图说话吧,下图就是我使用处理后的素材配合border-image
属性实现的效果:
大家看出来问题没有?
可能图有些小,看不到细节,我把边角放大 N 倍看下:
瞧见没有,border-image生成的图形藏在了图像内容的后面。
在Web中,content内容的层级是最高的,outline轮廓、border边框、background背景色等都是比图文内容的层级低的。
因此,border-image的图形在 IMG 元素内容的后面,导致边角的拖拽圈圈显示不全。
有一种解决方法是把 <img>
元素的src
地址改为使用 background-image
背景图实现,但这么做会影响浏览器默认的“复制图像地址”,“复制图像”等操作,最终的效果只是有形无实,这样的实现效果一定是没法通过马斯克的代码审查,是会被fire解雇的。
当技术无能为力的时候,可以从源头寻找解决方案,那就是……当当当当,改设计,当然,要和设计师提前沟通好。
至于能否沟通成功,一来看设计师的职业素养,二类看你个人的影响力,三是你自己的沟通能力,能不能把利弊方案等提前讲清楚。
所以,我就给设计师提了个方案(自己做了个图示意了下),能否类似这样的拉伸效果:
无疑议,直接通过。
变化在于,将拖拽图形全部改造为在图像元素的外部,这样就不会有被内容覆盖的问题了。
相关 CSS代码如下:
img.resizable, img[resizable] { border: 3px solid transparent; border-image: url(./作者zhangxinxu.svg) 12 / 12px / 0; }
OK,至此,最大的技术难度就解决了。
对,这个案例中,最大的技术难度就是 CSS 这一块,JS其实还好,就是手形和拖拽,这个有几年工作经验的前端都可以轻松驾驭。
三、眼见为实、demo与开源
代码码完上线之后,还有很多其他重要的事情要做。
包括撰写详细的文档,包括把项目中比较创新的地方总结梳理出来,包括项目小结文档和邮件等,这些工作很多人并不喜欢做,但对于个人的职业发展却很重要。
因为这些东西,你不讲,你不说,别人是不知道的,毕竟像马斯克这样会review代码的领导可是很罕见的,你不展现自己,说不定就会被浑水摸鱼的半吊子们取而代之,那多可惜啊。
回到这里。
为了总结自己的工作,同时方便自己日后复用,以及希望可以帮到其他遇到类似需求的人,所以我把相关的功能从生产环境剥离,独立成一个小小的开源项目,放在了 gitee 上了。
项目地址
单IMG元素的图像拉伸效果:https://gitee.com/zhangxinxu/only-img-resize
体验地址:https://zhangxinxu.gitee.io/only-img-resize/
使用说明
一开始我是做出直接引入JS就可以使用的那种,后来想想,有些参数还是必须的,所以还是改成了 export/import 模式。
<script type="module"> import onlyImgResize from './src/onlyImgResize.js'; onlyImgResize({ // 参数在这里 }); </script>
此时,页面中所有设置了类名 resizable,或者设置了 HTML 属性 resizable 的元素都可以四象拉伸。
使用很Easy~
语法和参数
语法如下:
onlyImgResize(options);
options
为可选参数,包括:
- selector
- 字符串值。默认值是
'.resizable, [resizable]'
,表示识别为可拉伸图片的选择器。 - maxWidth
- 数值或布尔值。默认是
true
,表示有最大宽度限制,最大宽度值是第一个非内联祖先元素的宽度。支持设置为数值,指定最大宽度值。如果设置为false,则表示图片尺寸的拉伸没有最大范围限制。需要注意的是,由于图片设置了透明边框,因为,100%宽度实际上会超出,实际最大宽度应该是calc(100% - 4px)
。 - whenDisabled
- 函数值,如果返回 true,表示禁用图像的拉伸,如果是 false,则拉伸执行。默认值是:
function () { return window.imgResizable === false || document.imgResizable === false; }
表示,如果
window.imgResizable
或者document.imgResizable
的值是false
,则禁用拉伸。此参数用在希望某些情况下,图片不被拉伸的时候。
- onFinish
- 函数值,默认是空函数,拖拽结束的时候触发。如果大家希望在其他事件,例如拖拽之中也有回调方法,fork该项目,然后自己添加即可。
其他
欢迎 Star,也欢迎关注我的 gitee 账户,会不定期更新一些自己的小玩具。
四、大浪淘沙始见金
好了,至此,正文内容就结束了。
其实深究起来,本文内容略“水”,还是多以自我展示为目的,真要说多少人会看到此文,多少人会学到这个小技巧,或者说受到启发,我并不抱多大的希望。
精力有限,我的公众号又不同步,掘金粉丝也不少,也懒得转一份(我做一件事情,一定是长期的,临时磨一枪,不如不做),更是让受众下降了不少。
可转念一想,写了快800篇原创技术文章了,哪一篇没有自我展示的目的呢?虽然当下,连我自己都没意识到这一点,但回过头看,实际上已经展示了自己。
也正因为有了这份展示,才能收获影响力,才能继续有动力坚持,纯粹的无人知晓的无私奉献注定是无法持久的,就好比在企业中默默干活却不去表达自己的老黄牛,老好人们。
这类人平时自我感觉不错,我对得起我自己,但遇到晋升绩效这样的事情的时候,因为结果不如意,又会感叹不公。
我称这类人为沉浸在让自己舒适的精神世界中的懒惰者,看起来干活勤勉,实际上是个懒人。
即使苦口婆心地反复强调,一定要花点功夫让同事和leader知道你做的工作,无论是量多,活苦,或者亮点都可以,但就是不做,宁可多接几个需求,就是不愿意做这样的事情,为什么呢?
因为做这种事情,跟他的个人作风,跟他的精神世界不符合,如果没有强迫的压力(如KPI之类的),绝对不会去打破这种精神舒适区的,会觉得不安全,直接躺平。
哎呀,这样冒头会不会不好啊?同事会怎样看我啊?项目没什么亮点,还发出去,会不会掉逼格啊?领导怎么看我啊?算了算了,同事都不发,我也懒得弄,做人要低调。
小说中有个桥段经典不衰,就是平时默默无闻,关键时候一鸣惊人,惊诧众人。
为何这样的桥段多呢?因为大多数的人平时就是默默无闻的,同时希望自己关键时候技惊四方。
喂喂喂,诸位,小说看多了吧,真以为是金字总会发光啊,那要需要有大浪淘沙的环境啊!
我们所处的时代,我们所在的团队,大多都是稳定状态的呀,是死水,是缓流,金字由于比重大,沉得更快啊,亲们!
平时不努力,关键时候想要让别人对你知根知底,是很危险的。
算了,不多扯了,家里领导喊我吃晚饭了。
总结下吧,平时多装逼,装着装着,你说不定真就牛逼了,平时少扮猪,装着装着,别人就真认为你是猪了。
对了,记得将此文到朋友圈,让你的leader知道你平时是爱学习的。
本文为原创文章,欢迎分享,勿全文转载,如果实在喜欢,可收藏,永不过期,且会及时更新知识点及修正错误,阅读体验也更好。
本文地址:https://www.zhangxinxu.com/wordpress/?p=10611
(本篇完)
- 移动端双指缩放图片JS事件的实践心得 (0.253)
- Chrome 88已经支持aspect-ratio属性了,学起来 (0.253)
- 理解CSS3 transform中的Matrix(矩阵) (0.228)
- 借助SVG文字尺寸自动缩放甚至突破Chrome 12px限制 (0.228)
- 检测DOM尺寸变化JS API ResizeObserver简介 (0.148)
- 如何使用JS检测用户是否缩放了页面? (0.148)
- 了不起的IE7浏览器-CSS新特性-实现与思维变革 (0.127)
- 实现兼容性的CSS粗虚线边框(dashed)效果 (0.103)
- 被低估的border-image属性 (0.103)
- IE矩阵滤镜Matrix旋转与缩放及结合transform的拓展 (0.101)
- 突发奇想,同步单复选框checked态岂不点击通杀? (RANDOM - 0.084)
学习了,并且已写了篇文章
https://juejin.cn/post/7227986137457229885
平时都是按照已经有的思路,直接复制,最多理解之后自己重写,也是一种复制, 都没有自己原创独特的思维,好惭愧
(纯当瞎说,既然都上JS了,
object-position: -9999px -9999px;
xxx.style.background = “url(” + yyy + “)”;
(不过编辑器仍然有可能鸽掉)
)
不过博主NB!
拉伸的最小宽度是不是也应该做一下限制,拖到最小图片就没了
有道理,欢迎 fork, 我合一下
“平时多装逼,装着装着,你说不定真就牛逼了,平时少扮猪,装着装着,别人就真认为你是猪了。”
— 哈哈,经典,但也得像你有实力才行!