7

JS之我用单img元素实现了图像resize拉伸效果

 1 year ago
source link: https://www.zhangxinxu.com/wordpress/2022/11/js-image-resize/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=10611 鑫空间-鑫生活
本文欢迎分享与聚合,全文转载就不必了,尊重版权,圈子就这么大,若急用可以联系授权。

欢迎光临,效果先行:

上为视频,不动轻戳。

如果您是使用PC机器阅读的本文,也可以点击此页面实际操作感受下。

如果查看源码,会发现只有个 img 元素,并无任何其他辅助:

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 账户,会不定期更新一些自己的小玩具。

2764.svg

四、大浪淘沙始见金

好了,至此,正文内容就结束了。

其实深究起来,本文内容略“水”,还是多以自我展示为目的,真要说多少人会看到此文,多少人会学到这个小技巧,或者说受到启发,我并不抱多大的希望。

精力有限,我的公众号又不同步,掘金粉丝也不少,也懒得转一份(我做一件事情,一定是长期的,临时磨一枪,不如不做),更是让受众下降了不少。

可转念一想,写了快800篇原创技术文章了,哪一篇没有自我展示的目的呢?虽然当下,连我自己都没意识到这一点,但回过头看,实际上已经展示了自己。

也正因为有了这份展示,才能收获影响力,才能继续有动力坚持,纯粹的无人知晓的无私奉献注定是无法持久的,就好比在企业中默默干活却不去表达自己的老黄牛,老好人们。

这类人平时自我感觉不错,我对得起我自己,但遇到晋升绩效这样的事情的时候,因为结果不如意,又会感叹不公。

我称这类人为沉浸在让自己舒适的精神世界中的懒惰者,看起来干活勤勉,实际上是个懒人。

即使苦口婆心地反复强调,一定要花点功夫让同事和leader知道你做的工作,无论是量多,活苦,或者亮点都可以,但就是不做,宁可多接几个需求,就是不愿意做这样的事情,为什么呢?

因为做这种事情,跟他的个人作风,跟他的精神世界不符合,如果没有强迫的压力(如KPI之类的),绝对不会去打破这种精神舒适区的,会觉得不安全,直接躺平。

哎呀,这样冒头会不会不好啊?同事会怎样看我啊?项目没什么亮点,还发出去,会不会掉逼格啊?领导怎么看我啊?算了算了,同事都不发,我也懒得弄,做人要低调。

小说中有个桥段经典不衰,就是平时默默无闻,关键时候一鸣惊人,惊诧众人。

为何这样的桥段多呢?因为大多数的人平时就是默默无闻的,同时希望自己关键时候技惊四方。

喂喂喂,诸位,小说看多了吧,真以为是金字总会发光啊,那要需要有大浪淘沙的环境啊!

我们所处的时代,我们所在的团队,大多都是稳定状态的呀,是死水,是缓流,金字由于比重大,沉得更快啊,亲们!

平时不努力,关键时候想要让别人对你知根知底,是很危险的。

算了,不多扯了,家里领导喊我吃晚饭了。

总结下吧,平时多装逼,装着装着,你说不定真就牛逼了,平时少扮猪,装着装着,别人就真认为你是猪了。

对了,记得将此文到朋友圈,让你的leader知道你平时是爱学习的。

1f609.svg

(本篇完)1f44d.svg 是不是学到了很多?可以分享到微信
1f44a.svg 有话要说?点击这里


Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK