原生 JS 手写一个优雅的图片预览功能,带你吃透背后原理
前言本文将用一个极简的例子详细讲解如何用原生JS一步步实现完整的图片预览和查看功能,无任何第三方依赖,兼容PC与H5,并介绍了如何仅通过指针事件进行多端统一的事件监听,如何实现触屏双指缩放等等,干货满满。
完整代码
为提升阅读体验,正文中代码展示均有部分省略处理。
点击查看完整源码
实现原理实现图片预览/查看的关键在于 CSS3 中的 transform 变换,该属性应用于元素在2D或3D上的旋转,缩放,移动,倾斜等等变换,通过设置 translate(x,y) 即可偏移元素位置,设置scale即可缩放元素,当然你也可以只设置 matrix 来完成上述所有操作,这涉及到矩阵变换的知识,本文使用的均是CSS提供的语法糖进行变换操作。
PC上的点击、移动,H5的手势操作,都离不开DOM事件监听。例如鼠标移动事件对应 mousemove,移动端因为没有鼠标则对应 touchmove,而本文将介绍如何仅通过指针事件来进行多端统一的事件监听。在监听事件中我们可以通过 event 对象获取各种属性,例如常用的 offsetX、offsetY 相对偏移量,clientX、clientY 距离窗口的 ...
你真的了解 CSS 径向渐变吗?
本文翻译自:《Do you really understand CSS radial-gradients?》所有第一人称口吻均指原作者本人,作者是 Microsoft Edge 开发人员体验团队的 PM,之前曾在 Mozilla 工作。
前言2022 年 10 月 24 日
七年前,我自学了所有关于CSS 线性渐变的知识,从那以后,我一直想了解更多关于径向渐变的工作原理。我花了很长时间才找到一个借口来深入挖掘其背后的逻辑,很庆幸我做到了。
为了学习如何使用radial-gradient CSS 功能,我尝试仅使用 CSS 绘制一双眼睛,仅使用一个元素 par eye,并且仅使用径向渐变。你可以看到是下面这个结果:
https://code.juejin.cn/pen/7159818547550486535
当然,这不是你见过的最好的人眼图(另外,它在 Safari 中无法正确渲染,请参阅浏览器支持部分中的原因),但它确实帮助我更多地了解径向渐变很有效,通过这篇文章,我希望你也能从中学到一两点。
语法描述从专业领域上讲,radial-gradient 语法如下所示:
1radial- ...
如何用 JavaScript 编写你的第一个单元测试
测试代码是确保代码稳定的第一步。能做到这一点的最佳方法之一就是使用单元测试,确保应用程序中的每个较小的功能都按应有的方式运行——尤其是当应用程序接收到极端或无效输入,甚至可能有害的输入时。
为什么要进行单元测试?进行单元测试有许多不同的方法,一些主要目的是:
验证功能:单元测试确保代码做正确的事情并且不做任何不应该做的事情——大多数错误发生在这里。
防止代码回归:当我们发现错误时,添加单元测试来检查场景可以防止代码更改在将来重新引入错误。
记录代码:通过正确的单元测试,一套完整的测试和结果提供了应用程序应该如何工作的规范。
保护您的应用程序:单元测试可以检查可利用的漏洞(例如启用恶意 SQL 注入的漏洞)。
范围界定和编写单元测试使用单元测试框架使我们能够快速编写和自动化我们的测试,并将它们集成到我们的开发和部署过程中。这些框架通常支持前端和后端 JavaScript 代码的测试。
以下是帮助你编写性能单元测试和可测试代码的一些通用指南。
保持单元测试简短而简单不要编写过重的单元测试,测试应该只有几行代码来检查应用程序的简短功能块。
考虑正面和负面的测试用例虽然编写正确执行函数的测 ...
如何编写一个原生WebComponents组件
当今前端编程中,利用语义化的 HTML 结合 CSS 来完一个组件并不是一件难事,这也意味着无论在 React、Vue 中都可以插入,不过它俩不是今天的主角,接下来我将用一个例子来介绍如何封装一个完整的原生 HTML 的 Web Components 组件,让我们开始吧!
HTML结构首先我们来了解下 HTML 中的 <details> 元素,它可以用于创建一个小部件,其中包含仅在小部件处于“打开”状态时才可见的附加信息,<details>元素内可以包含的内容没有任何限制。
默认情况下,元素创建的小部件<details>处于“关闭”状态(open标签可使其打开)。通过单击小部件在“打开”和“关闭”状态之间切换,以显示或隐藏标签中包含的附加信息,内部标签 <summary> 元素则可为该部件提供概要。
一个简单的例子如下:
1234<details> <summary> 不能说的秘密 </summary> 藏的这么深,可还是被你发现了</details>
1234567891 ...
这道JS经典面试题不要背,今天带你彻底搞懂它!
前言这是一道非常经典的面试题,涵盖了从函数的基本概念、运算符优先级,到作用域链、原型链、this关键字、new关键字等基础知识点考察,可以说能完整答对 JS 基础才算过了关,本文就带大家回顾并剖析这道面试题,应该是全网最详细的文章了,这次彻底搞懂它。
1234567891011121314151617181920212223// afunction Foo () { getName = function () { console.log(1); } return this;}// bFoo.getName = function () { console.log(2);}// cFoo.prototype.getName = function () { console.log(3);}// dvar getName = function () { console.log(4);}// efunction getName () { console.log(5);}
...
Vue项目处理错误上报如此简单
处理异常的意义随着网页项目越来越复杂,许多异常报错很难在开发和测试阶段被发现,尽管你可能避开了语法等常规错误,但不可避免的是代码在运行时的错误你仍旧无法准确预料,假设现在有如下一段 Vue 代码,它在生命周期的 created 阶段异步请求并接收了错误的数据,可能就会导致页面渲染出现错误:
1234567891011121314<template> {{ test.obj.xxx }}</template>......created() { this.getSomeData()},methods: { getSomeData() { this.fetch().then((res) => { this.test = res // 假设这是请求的错误数据 }) },}
而如果测试人员及时发现了这一错误的话,当他打开控制台时往往就会立即下结论了:噢,是前端的锅🙂
事实上真正的项目中可能 ...
Vue实现无限级树形选择器(无第三方依赖)
想要在 Vue 中实现一个这样的无限级树形选择器其实并不难,关键点在于利用 递归组件 和 高阶事件监听,下面我们就一步步来实现它。
简单实现下样式创建 Tree.vue 组件(为方便阅读,代码有省略):
123456789101112131415161718192021222324252627282930313233343536373839<template> <ul class="treeMenu"> <li v-for="(item, index) in data" :key="index"> <i v-show="item.children" :class="triangle" /> <p :class="treeNode"> <label class="checkbox-wrap" @click="checked(item ...
原生拖拽太拉跨了,纯JS自己手写一个拖拽效果,纵享丝滑
前言提到元素拖拽,通常都会先想到用 HTML5 的拖拽放置 (Drag 和 Drop) 来实现,它提供了一套完整的事件机制,看起来似乎是首选的解决方案,但实际却不是那么美好,主要是它的样式太过简陋,无法实现更高级的用户体验:
这是浏览器默认的拖拽效果,点住拖拽任意图片或文字都会产生。
笔者因为之前有个小项目需要经常参考稿定设计,一直有留意其元素拖拽的效果(如下图),所以接下来我将以这种效果为蓝本,使用原生 JS 实现一个富有动感的 自定义拖拽 效果,话不多说直接开摸。
实现原理首先说下思路,我们需要知道鼠标的三个事件,分别是 mousedown,mousemove,mouseup ,当点击按下的时候,克隆一个绝对定位的元素,并标识下”拖拽中”的状态,接着在 mousemove 中就可以判断应该执行的具体方法,从而让元素随着鼠标移动起来。
在监听事件的 event 对象中,有几个参数是比较重要的:clientX,clientY 标识的鼠标当前横坐标和纵坐标,offsetX 和 offsetY 表示相对偏移量,可以在 mousedown 鼠标按下时记录初始坐标,在 mouseup ...
如何优雅地编写一个高逼格的JS插件?
在一个风和日丽的早晨,我正悠闲地喝着Coffe,突然领导向我走来,我赶紧熟练地切出VSCode,淡定自若地问:领导,什么事?领导拍了拍我的肩膀:你上次封装的方法同事跟我反馈使用起来很不错啊,你不如做成JS插件给大家用吧。我放下了手中的马克杯,甩了一下眼前仅剩的几根刘海:没问题啊,小Case!随即开始摸鱼….
原型链写法要开始编写插件就得先了解JS模块化,早期的模块化是利用了函数自执行来实现的,在单独的函数作用域中执行代码可以避免插件中定义的变量污染到全局变量,举个栗子🌰,以下代码实现了一个简单随机数生成的插件:
1234567891011121314151617181920212223;(function (global) { "use strict"; var MyPlugin = function (name) { this.name = name }; MyPlugin.prototype = { say: function () { ...
在Chrome浏览器中最快速实现拾色器(颜色吸管)的方法
说到网页拾色器(颜色吸管工具)在前端的实现方法,通常我们会想到先进行网页截图,然后通过Canvas绘制截图,此时利用Canvas所提供的的API即可解析出图片每个像素点颜色,最后通过获取鼠标定位,得到当前的坐标来进行颜色选择。
在这种方式下通常问题出在第一个步骤,就是进行网页截图的方法,在前端网页截图常见的工具有:html2canvas、dom-to-image 等,然而这些库的实现原理都是通过解析DOM然后转换语法(Canvas 或 Svg)绘制再导出图片,虽然这是目前实现截图操作的唯一出路,但我们要清楚的是这样做不可避免会出现以下问题:
对于复杂网页场景解析可能会出现缺失或错误
无法避免 Canvas 或 Svg 的渲染结果与网页呈现效果存在差异的问题
生成效率太慢,解析绘制过程会造成卡顿,非常影响用户体验
所以基于此思路做出来的颜色吸色器尽管在设计初期就考虑可用性,也仍然无法避免上述问题,最多只能应用于简单网页的场景当中,但这通常又与事实相违背——因为简单的网页往往极少有使用到吸色器的业务场景。
原生方案如果说 JS 的实现方法是令人沮丧的,那么把问题交给浏览器原生方法可能是 ...






