蓝色的秋风

蓝色的秋风 查看完整档案

杭州编辑  |  填写毕业院校美团  |  web前端 编辑 qiufeng.blue 编辑
编辑

JavaScript开发爱好者。全栈工程师。

📬微信公众号:秋风的笔记
📘博客主页:https://qiufeng.blue

个人动态

蓝色的秋风 回答了问题 · 3月1日

给body添加全屏背景图(backgroung-size:cover),如何给图片上某一个区域添加点击事件,适应各个分辨率

使用 background-size: cover

缩放背景图片以完全覆盖背景区,可能背景图片部分看不见。和 contain 值相反,cover 值尽可能大的缩放背景图像并保持图像的宽高比例(图像不会被压扁)。该背景图以它的全部宽或者高覆盖所在容器。当容器和背景图大小不同时,背景图的 左/右 或者 上/下 部分会被裁剪。

首先你在原图获取点击的位置,例如原图是 300 * 400 ,你的点击位置是 left: 150 , top: 200, 然后获取屏幕分辨率的宽度和高度,来计算。如果屏幕宽度/屏幕高度大于 3/4 ,说明他会按照宽度来拉伸,此时如果屏幕宽度为 400px,高度为400px, 那么位置计算为,ratio = 4/3 , newLeft = 150 * 4 / 3, newTop = 150 * 4 / 3。 如果是如果屏幕宽度/屏幕高度小于 3/4,如果此时,屏幕宽度为200,高度为 800,说明他会按照高度的比例来计算,因此,你的 ratio = 800/400 , newLeft = 150 * 2 ,newTop = 150 * 2

关注 6 回答 5

蓝色的秋风 发布了文章 · 2月19日

2021前端学习路径书单—自我成长之路

正式学习前端大概 3 年多了,接触前端大概 4 年了,很早就想整理这个书单了,因为常常会有朋友问,前端该如何学习,学习前端该看哪些书,我就讲讲我学习的道路中看的一些书,虽然整理的书不多,但是每一本都是那种看一本就秒不绝口的感觉。

以下大部分是我看过的,或者说身边的人推荐的书籍,每一本我都有些相关的推荐语,如果你有看到更好的书欢迎推荐呀。

前端学习书籍导图-1

JS

《JavaScript高级程序设计(第4版)》

第三版:豆瓣评分9.3

第四版:豆瓣评分8.5

现在建议学习第四版,因为第三版很多还是以ES5的语法进行讲解的,目前主流都是 ES6 语法了。当年我入门这是我看的第一本JS书籍,也是实验室的导师推荐的,这本书很厚,真的需要耐着性子看完,DOM、BOM、JS基础语法,我先是把这些大概的过了一下,然后去实践项目,有不懂的点再来回味这本书,以我的性子,还是比较喜欢动手进行实践。

《你不知道的JavaScript(上卷)》

豆瓣评分 9.3

这本书,真的是神书,我先看的高级程序设计,但是看完我对一些作用域啊,闭包,原型链还是懵懵懂懂,看完这本书瞬间打通了任督二脉,豁然开朗。

《ECMAScript 6 入门电子版》

《ECMAScript 6 入门》

豆瓣评分 8.8

这本书属于工具书,建议电子版,翻翻常用的一些 ES6 语法就好了,当年我准备实习的时候就看了常用的一些语法例如(Map、Set、Proxy、Promise、Generator、async、Module等)。(当然如果对你有帮助还是可以买一下实体书,支持一下作者,毕竟电子版可以免费看,写书需要花很多精力。)

《JavaScript忍者秘籍(第2版)》

豆瓣评分 8.5

这本书是我工作上的导师推荐,我暂时还没看,据说帮助他解了很多疑惑。

CSS

《CSS世界》

作者是张鑫旭,可以说是 CSS领域的鼻祖了。我买了这本书,但是还没有看,不看的原因不是他不好,是最近不常写CSS了,哈哈哈。当初买它的时候,我是看它的目录,可以说它把CSS中一些比较重要的场景都包含到了。目录名字也取得非常有吸引力。块级元素、盒子模型、浮动、层叠规则等等基础的用法都讲到了。

《CSS揭秘》

豆瓣评分 9.4

作者是Lea Verou,W3C CSS工作组特邀专家,设计CSS语言的委员之一,此前曾在W3C担任开发者代言人。目前,她在麻省理工学院从事人机交互领域的研究。

作者来头真的太大了...又是W3C CSS专家又是MIT的...看过这本书的人都会惊叹,原来 CSS 还能这么玩?如果你想精进 CSS,这本书不能错过。这本书刚出的时候就买了,后来毕业送给了实验室的小伙伴。

框架

Vue

vue2文档

vue3文档

如果出个豆瓣评分估计是9.9分,那0.1分怕它骄傲。

vue的学习建议直接看官网吧,写的太详细了,像一本书一样。

React

React官网

官网教程真的很贴心,会一步一步教你如果构建一个 React 应用,并且还会说有些哲学思想。

《React小书》

这本书是一本开源的书籍,面向的对象是有一点前端基础的并且是 React.js 零基础的同学而作。

《深入React技术栈》

豆瓣评分 8.1

大概是 17 年的时候买的,算是买的第一本 React 书籍也是唯一一本 React 书籍,

Node

《七天学会NodeJS》

开源书,书只有大概只有200页左右,一下子就能看完,通过例子能够快速熟悉一些 Node 的 API,也许现在来说很多 API 已经过时了(毕竟Node版本迭代太快了,现在都15x了),但是安装旧版本的 Node来入门,仍然是一本和不错的书。

《深入浅出Node.js》

豆瓣评分 8.6

清晰地讲解了Node.js 底层原理,以及如何使用 Node.js 进行工程项目开发,是进阶的首选。

《Node.js设计模式》

原书英文版豆瓣评分9.5,买了中文版...看的云里雾里,可以试试英文版。

《Node.js:来一打 C++ 扩展》

刚出的时候就买了这本书... 但是功力不够啊,看这本书需要一些 C++ 的底蕴,还特地买了 C++ Primer 准备好好学习,但是发现...周期太长了没有坚持下来,又因为公司也没有这方便的场景应用,所以自己草草写了一个 C++ 插件(https://github.com/hua1995116/LRU-node-addon)之后,这本书就搁置了。

工程化

Webpack

《深入浅出Webpack》

《深入浅出 Webpack电子版》

这本书很多人吐槽,说写的很基础,深度不够,也比较落后了。确实是这样,但是我觉得webpack官方文档虽然很全很前沿,但是还没有那种一下子就能让人整明白的。跟着这本书 + 配套github示例,写完全部示例(花不了很多时间),可以说对 webpack 会有一个大概的了解。

学习webpack难点在于什么?

各种周边插件版本不配套啊!

想加个loader/plugin,各种版本不兼容,各种报错!因为新手安装 webpack 的插件大多数人都是会安装到最新版本,但是最新版本大多数会有各种问题,真的是劝退...

webpack经过几个飞速的迭代,webpack3x和4x的插件机制就不一样,现在又是5x了。

所以能有一个固定的版本,跟着走完全流程对它有一个整体的认识,看完一本书能了解这些也算是值了。有了这些整体的认知,相信你不管是学 4x还是5x都能行云流水了。

TypeScript

深入理解 TypeScript》

开源电子书,是一个学习 TypeScript 不错的开始吧,我快速过了一下这本书和官网示例,有了大概的了解,想要深入学习 TS 可能还是需要实践吧~

《重学TS》

阿宝哥写的重写 TS 也很不错,其实我TS用的并不多,偶然在写一些高级泛型的时候查到了阿宝哥写的文章,感觉受益良多。

计算机基础

设计模式

JavaScript设计模式》

以故事线的模式来风趣地讲解JS的设计模式。

算法基础

《图解算法》

豆瓣评分 8.4

小白也能看懂的算法,对于初学者可以说非常有帮助,我看完了电子版,但是对于想真正在算法领域有所精进那就看下面这本书吧。

《算法导论》

豆瓣评分 9.2

这本书很数学,看的令人头秃,但是真的很全,里面的示例全部是伪代码所写,理解起来也有一定的难度,跟着实验做一遍会有很大的收获。

网络基础

《图解 HTTP》

豆瓣评分 8.1

这本书也是看了电子版,主要是围绕TCP/IP来进行讲解,浏览完对HTTP常用的一些属性以及网络会有一个大概的概念。

《TCP/IP详解 卷1:协议》

豆瓣评分 9.2

如果要精进计算机网络,可以看这本。

编译原理

《编程语言与实践》

买了龙书啊虎书啊什么的,看了都犯困,而这本书只看了前几章,就能自己实现了一个ll(1)的解释器 common-comment-parser

代码规范

《重构》

豆瓣评分 9.4

第2版和第1版我都买了,看完确实对写代码有帮助,其中重构前最重要的就是保证不破坏原先的代码的逻辑,这就要求我们有足够的测试用例情况下再进行重构。

技术探索

Three.js

《Three.js 入门指南》

可能对于大佬来说比较基础,但是对于小白入门来说,是不错的选择。能了解三维世界中的照相机、材质、网格和动画等特性。

《Three.js 开发指南(第三版)》

还正在看中,买了当当的电子版。

Serverless

《深入浅出Serverless》

这本书我是在微信读书看的,看了一半,可以对 Serverless 到底是什么东西有所了解,Faas 并不是代表 Serverless,Serverless 是由 Faas + Baas 组成的,容器化发展过程,Serverless的特点都在本书进行了讲解。

为了证明以上大部分书我确实都是自己读过才推荐的,晒一下我的书柜(像你不知道的JS以及深入React技术栈在毕业的时候送给实验室小伙伴了,还有一些看的电子书~)

IMG_1394

结语

❤️关注+点赞+收藏+评论+转发❤️,原创不易,鼓励笔者创作更好的文章

关注公众号秋风的笔记,一个专注于前端面试、工程化、开源的前端公众号 ![]

  • 关注后回复简历获取100+套的精美简历模板
  • 关注后回复好友拉你进技术交流群+面试交流群
  • 欢迎关注秋风的笔记
查看原文

赞 33 收藏 25 评论 2

蓝色的秋风 发布了文章 · 2月15日

JS也可以这么浪漫,用JS写下一个世界(VR)

先上图感受一下,以迪士尼城堡为例。

640-1

640-4

心动了吗?你以为实现这个炫酷特效会很复杂?

不不不,实现这个特效只有两个步骤

  • 需要一张全景图
  • 使用 photo-sphere-viewer.js 进行配置 (一个用来来显示全景图JavaScript库)

可以从这里免费下载全景图片

https://pixabay.com/zh/images...

在线演示地址(手机打开效果更佳) https://qiufeng.blue/frontend...

1613375898884

源码地址: https://github.com/hua1995116...

代码详解

<style>
#photosphere {
    width: 100%;
    height: 100%;
}
</style>
</head>
<body>

<div id="photosphere"></div>

<script data-original="three.js"></script>
<script data-original="browser.js"></script> /*uEvent 的浏览器版本*/
<script data-original="photo-sphere-viewer.js"></script>

<script>
  const PSV = new PhotoSphereViewer.Viewer({
    container : 'photosphere', // 容器id
    panorama  : '360.jpg', // 全景图地址
    caption   : '',
    loadingImg: 'assets/photosphere-logo.gif', // loading的gif
    defaultLong: Math.PI/2 + Math.PI/12, // 默认角度
    defaultZoomLvl: 30,
  });
</script>
<script data-original="./snow.js"></script> /*下雪的场景*/

实现上面场景的代码非常简单,主要是有photo-sphere-viewer.js实现的,自己不需要加任何代码。

photo-sphere-viewer.js 也支持了非常多的控件,例如 mark 标记自动漫游以及设置分辨率等。

由于 photo-sphere-viewer.js 是基于 Three.js ,因此必须引入 Three.js 的依赖,还依赖 uEvent 事件订阅相关的 API。

我再来看看增加插件会有哪些不一样的变化。

我们可以通过 mark插件来标记一些特殊的地点,并且还有标记列表,可以直达对应的地点。通过增加对应的点位来实现呈现出特殊意义的位置,可以是第一次相遇或者是第一次做了不可描述画面的地点(小朋友捂脸)...

PSV = new PhotoSphereViewer.Viewer({
  ...
    plugins: [
      [PhotoSphereViewer.MarkersPlugin, {
        markers: (function () {
          var a = [];

          a.push({
            id: '#123',
            tooltip: '第一次相遇的地点',
            latitude: -0.3988129280019779,
            longitude: 1.7374233460711157,
            image: 'assets/pin-red.png',
            width: 32,
            height: 32,
            anchor: 'bottom center',
          })
          return a;
        }())
      }]
    ]
    ...
})

var markers = PSV.getPlugin(PhotoSphereViewer.MarkersPlugin);
markers.toggleAllTooltips();

1613375926141

mark 不仅可以标记地点,还可以通过列表来进行引导

640-3

关于这个 snow特效是我随便找的一个js特效,你也可以通过不同的场景,换成雨、下星星啊,各种浪漫的场景~

赶紧收藏这个效果吧~

结语

❤️关注+点赞+收藏+评论+转发❤️,原创不易,鼓励笔者创作更好的文章

关注公众号秋风的笔记,一个专注于前端面试、工程化、开源的前端公众号

  • 关注后回复简历获取100+套的精美简历模板
  • 关注后回复好友拉你进技术交流群+面试交流群
  • 欢迎关注秋风的笔记
查看原文

赞 14 收藏 12 评论 0

蓝色的秋风 发布了文章 · 2月14日

Github域名加上`1s`,在线VS Code阅读源码神器诞生

近日,一款域名为 github1s 开源项目诞生了,正如他的名字所说,只要在 github 地址上面加上 1s,就能秒级用在线 VS Code 打开 github 项目,这可以说为开发者带来了巨大的便利!!!

我们来看看这个项目打开后长什么样子~

以大家广为知道的 React 为例,只要将 github 替换成github1s

http://github.com/facebook/react

http://github1s.com/facebook/react

然后我们来谈谈这个项目的优缺点

优点

几乎拥有和本地 VS Code 一样的界面

在在线 VS Code 中打开,同样的款式同样的配方,这样阅读起来非常有亲切感,这种亲切感,可以更好地提高我们阅读代码的效率。

支持 VS Code 中的部分快捷键

能够 command + 单击 (window 应该是 ctrl + 单击)自动跳转到对应的函数。

支持 hover 后能够推导类型

支持代码收起和展开

这个功能对阅读源码非常有帮助,可以帮助我们收起一些不重要的函数,让我们摸清代码的主干。

支持代码在线比较

选中两个文件右键,就可以进行在线比较

一键下载单文件

对于 Github 站点上阅读整体目录不便的情况下,并且下载文件总是需要点击 Raw 再下载源文件,可以说这个功能方便太多了。(当然你也可以下载一些其他的插件)

缺点

不能点击文件跳转至其他文件

目前的版本中是无法直接点击引用文件自动打开其他文件

无法全局搜索

只有当我们打开了当前的文件,才会从当前打开的页面中进行全局搜索,没有打开的页面没办法全局搜索,这样对大型库的源码阅读还是造成了一定的影响。

技术探索

在 api 层面看到主要还是走了 github 的开放接口,这样有个问题就是我们国内用户,访问起来还是没法达到1s那么快,但是我的网络基本上3s初次渲染也完成了。

总结

带来了一定的便利,比纯用 github好用多了,也比 sourcegraph 插件使用起来体验更好!但是想要完全替代本地编辑器阅读源码,任然需要完善,例如上述说到的缺点。

综上源码阅读体验排名:

本地VS Code > Github1s > sourcegraph > Github站点

如果还有什么我没有发现的优缺点,欢迎留言中指出~

最后

回看笔者往期高赞文章,也许能收获更多喔!

结语

❤️关注+点赞+收藏+评论+转发❤️,原创不易,鼓励笔者创作更好的文章

关注公众号秋风的笔记,一个专注于前端面试、工程化、开源的前端公众号

  • 关注后回复简历获取100+套的精美简历模板
  • 关注后回复好友拉你进技术交流群+面试交流群
  • 欢迎关注秋风的笔记
查看原文

赞 16 收藏 6 评论 5

蓝色的秋风 赞了文章 · 2月11日

JParticles 2.0 发布,打造炫酷的粒子特效

JParticles 2.0 发布,打造炫酷的粒子特效。
不好意思哈,在这么繁花似锦的世界里,标题不得不取得吸引眼球一点哈,
不然...还是不啰嗦了,我们进入正题吧图片描述

简单介绍一下

JParticles 2.0 版本之前还叫 Particleground.js,相信在用的朋友应该不会陌生,关于 1.x 版本的宣传文案可以移步看这里哈,或许可以帮助你了解 JParticles 2.0 的一些东西。

我们一贯的理念

我们(我/笑哭)一贯的理念是信仰:"The Write Less, Do More""Keep It Simple And Stupid"
希望插件工具什么的使用起来非常的简单便捷,上手快,不耽误人们宝贵的时间,尤其是在变化迅速的前端,
希望我们的 代码写得简洁,简单,易懂API设计的简洁,简单,易用, 最后 强大,易扩展

此次版本更新日志

看看我们这次版本更新了哪些东西吧,biubiu...贴图:

图片描述

貌似挺多的,主要我们还是只讲三点吧,剩下的可以看官网慢慢了解,哈哈。

第一点:视差粒子

https://codepen.io/barrior/pe...

几行 JavaScript 代码:

为了看起来更简洁,定义视差粒子层数的属性就省略了,因为本身它就是 3 层,也挺好的。
CodePen 演示四层,为了让大家能更了解属性的使用方法。

new JParticles.particle('#demo', {
  // 开启视差效果
  parallax: true,
  
  // 定义视差强度
  parallaxStrength: 1
});

是不是好少...少到想哭有木有,但是很酷炫~

第二点:模拟语音搜索

学习于京东APP的搜索,上图:

图片描述

https://codepen.io/barrior/pe...

JavaScript 代码:

如果你使用过 1.x, 相信你对 wave 的参数配置很理解,
我们删除了之前的旧方法 setOffsetTop(),添加了新方法:setOptions()
这个方法就更加强大与自由了,可以控制更多的属性的变化,达到我们想要的效果。
这里我们主要的控制就是这个方法了,只是按住这个自定义事件是用户自己的行为,
所以这里贴上自定义代码把我们简洁的 API,弄的好像很复杂了一样,冤枉~
其实一共就两处,见下面标注。

var settings = {
  crestHeight: [10, 14, 18],
  speed: .1
};

// 这里是第 ① 处
// JParticles.utils.extend 等同于 jQuery.extend,你也可以使用 Object.assign 替代。
var effect = new JParticles.wave('.instance .demo', JParticles.utils.extend({
  num: 3,
  lineColor: ['#e53d27', '#42e527', '#27C9E5'],
  lineWidth: [.7, .9, 1],
  offsetTop: .65,
  rippleNum: 2
}, settings));

// 线条波动效果
document.querySelector('.voice').onmousedown = function () {
  clearInterval(this.timer);
  this.timer = setInterval(function () {
    var crestHeight = settings.crestHeight.map(function (item) {

      // 获取随机波动值
      item += JParticles.utils.limitRandom(20, -20);

      // 处理 (0, 1) 之间的值为整数
      if (item < 1 && item > 0) {
        item = Math.ceil(item);
      }

      return item;
    });

    // 这里是第 ② 处
    // 通过 setOptions() 来控制线条的波动
    effect.setOptions({
      crestHeight: crestHeight,
      speed: [.2, .14, .1]
    });
  }, 100);

  // 复原
  var self = this;
  document.onmouseup = function () {
    document.onmouseup = null;
    clearInterval(self.timer);
    effect.setOptions(settings);
  };
};

第三点:waveLoading 模拟进度条加载

这是一个封装好的,简单易用的模拟加载进度条动画。

1.x 版本是通过 wave 这个波浪运动来手写加载进度条的内容,并不是很方便,参数的控制也麻烦,
于是 2.0 着重封装了这个模拟加载进度条的动画,这个特效在单页应用首次加载什么的还是很需要的吧。
又高大上,又可以缓解加载的等待心情。

现在就来看看是怎么简单的使用这个功能特效吧,我们以加载 baidu.com 首页为示例,貌似其他的不允许 iframe 加载:

https://codepen.io/barrior/pe...

简单的 JavaScript 代码(CodePen 的代码是有对细节进行调整,而核心内容就是下面这么简单):

var demo = document.querySelector('.demo');

// 生成 loading 动画
var loading = new JParticles.waveLoading(demo);

// 当你告诉 loading 加载完了,loading 就加载结束,并触发这个事件
loading.onFinished(function () {
    
    // 这时,你就可以删除 loading 动画了,让页面显示出来
    demo.parentNode.removeChild(demo);
});

// 加载完,告诉 loading 加载完了,让 loading 结束
// 因为这是模拟进度条,所以你得告诉 loading,它才知道页面此时已经加载完了
window.onload = function () {
    loading.done();
};

致歉

这个还是得致歉,之前承诺的会在新版增加QQ登录背景效果(Delaunay三角的实现),由于时间也挺赶的,
现在还没研究出Delaunay三角的实现,当然其实也可以用等研究好三角函数做出效果来了再发,但是这样就耽误的新版的发布,还不如先把能用的发出来,先用着能用的,后续再慢慢添加其他有意思的东西进来。
此处,对看过更新日志并满怀期待的同志表示深深的歉意!

最后

官网(我想这应该是一个非常棒的文档,因为很用心在写):jparticles.js.org
如果你喜欢这个插件库并能帮助到你的实际工作中,希望它能发展的更好,提供更多有趣实用的特效,支持作者,烦请点个 Star O(∩_∩)O谢谢~。

查看原文

赞 12 收藏 16 评论 10

蓝色的秋风 发布了文章 · 2月8日

教你实现微信8.0『炸裂』的🎉表情特效

写在开头

最近微信更新了8.0,其中之一最好玩的莫过于表情包的更新了,大家都在群里纷纷玩起了表情包大战。

作为一个前端程序员,这就勾起了我的好奇心,虽然我从来没有实现过这样的动画,但是我还是忍不住想要去实现,最终我花了2天时间去看一些库的源码到我自己实现一个类似的效果,在这里我总结一下,并且手把手地教大家怎么学习实现。而🎉有一个自己的名字,叫做五彩纸屑,英文名字叫 confetti

聊天室+五彩纸屑特效 在线地址: https://www.qiufengh.com/#/

聊天室Github地址: https://github.com/hua1995116/webchat

五彩纸屑Github地址: https://github.com/hua1995116/node-demo/tree/master/confetti

特效预览,时间原因我只实现了平行四边形的彩色小块,其他形状的原理也是类似。

还可以设置方向

前期研究

在写这个特效前,我几乎不会用canvas,虽然说现在也不太会用,很多 API 也不太清楚,因此这篇教程也是基于零基础 canvas 写的,大家不用担心这个教程难度太高而被劝退。我会通过零基础 canvas 的基础上来一步步实现的。不过学习这个特效之前需要一点点高中数学的知识,如果你还记得 sin 和 cos 函数,那么以下的内容对于你来说都会非常简单,不会也没关系~

我个人比较喜欢探索研究,对有意思的玩意儿就会去研究,因此我也是站在巨人的基础上,去 codepen 查了好多个类似的实现进行研究。

最终将目标定位在了 canvas-confetti ,为什么是这个库呢?因为他的效果对于我们来说非常可以了,而且它是一个开源库,并且拥有了 1.3K star(感觉改天可以分析分析大佬实现库的原理了~),维护频率也非常高。

核心实现

切片场景

首先拿到这个库的时候,我有点开心,因为这个库只有一个单文件。

但是,当我打开这个文件的时候,发现不对...1个文件500行代码,我通过剥离层层的一些自定义配置化的代码,最后抽离出单个纸屑的运动轨迹。我就开始不断地在观察它的运动轨迹...无限循环的观察...

可以看到它在做一个类似于抛物线的运动,然后我一一将源码中的变量进行标注,再结合源码。

fetti.x += Math.cos(fetti.angle2D) * fetti.velocity;
fetti.y += Math.sin(fetti.angle2D) * fetti.velocity + fetti.gravity; 

以上代码看不懂也没事,我只是证明一下源码中的写法,并且提供学习源码的一些思路,以下才是真正的开讲实现!

平行四边形的实现

实现这个特性前,我们需要知道 canvas 几个函数。更多查看(https://www.runoob.com/jsref/dom-obj-canvas.html)

beginPath

方法开始一条路径,或重置当前的路径。

moveTo

把路径移动到画布中的指定点,不创建线条。

lineTo

添加一个新点,然后在画布中创建从该点到最后指定点的线条。

closePath

创建从当前点回到起始点的路径。

fill

填充当前绘图(路径)。

fillStyle

设置或返回用于填充绘画的颜色、渐变或模式。

既然我们要实现五彩纸屑,那么我肯定得先实现一个纸屑,我们就来实现一个平行四边形的纸屑吧!

我们都知道在 css 中实现平行四边形就是一个div,默认就是一个盒子,而在 canvas 中并没有那么方便,那么怎么实现一个平行四边形呢?

四个点,我们只需要知道四个点,就能确定一个平行四边形。而canvas中的坐标系和我们普通的写网页略有不同,它是从左上角作为起始点,但是并不影响。

我可以来画一个宽为20的平行四边形,(0, 0), (0, 20), (20,20), (20,0)

...(省略了一些前置初始化代码)
var context = canvas.getContext('2d');
// 清除画布
context.clearRect(0, 0, canvas.width, canvas.height);
// 设置颜色并开始绘制
context.fillStyle = 'rgba(2, 255, 255, 1)';
context.beginPath();
// 设置几个点
var point1 = { x: 0, y: 0 }
var point2 = { x: 0, y: 20 }
var point3 = { x: 20, y: 20 }
var point4 = { x: 20, y: 0 }
// 画4个点
context.moveTo(Math.floor(point1.x), Math.floor(point1.y));
context.lineTo(Math.floor(point2.x), Math.floor(point2.y));
context.lineTo(Math.floor(point3.x), Math.floor(point3.y));
context.lineTo(Math.floor(point4.x), Math.floor(point4.y));
// 完成路线,并填充
context.closePath();
context.fill(); 

我们总结一下,我们其实只需要一个点就能确定这个平行四边形的初始位置(0, 0),如果再知道一个角度(90度)、以及平行四边形的变长(20)就能确定整个平行四边形的位置了!(仅仅只需要初中知识就能定位整个平行四边形)。

好了,你学会画这个已经离成功迈向了一大步!是不是挺简单的~

大佬们内心OS: 就这?

嗯,就这。

运动轨迹

通过不断地调试 canvas-confetti 每一帧的轨迹运动,发现它始终做的是一个x轴变减速运动(直到速度为0就不继续运动了),而y轴也是一个先变减速运动再是一个均速运动,以下是大致的轨迹图。

这就是他的运动轨迹,别以为看着挺难的,但是核心代码只有三句。

// fetti.angle2D为一个角度(这个角度确定了运动轨迹 3 / 2 * Math.PI - 2 * Math.PI之间的一个值,由于要让轨迹往左上角移动,就是都要往负方向运动,因此选了以上范围),
// fetti.velocity 为一个初始为50长度的值。
// fetti.gravity = 3
fetti.x += Math.cos(fetti.angle2D) * fetti.velocity; // fetti.x 第一个点的x坐标
fetti.y += Math.sin(fetti.angle2D) * fetti.velocity + fetti.gravity; // fetti.y 第一个点的y坐标
fetti.velocity *= 0.8; 

总结起来就是,第一个坐标点的 x 周始终在增加一个负值(Math.cos(3 / 2 Math.PI - 2 Math.PI) 始终为负值),这个值在不断减小。而第一个点的y轴也始终在加一个负值Math.cos(3 / 2 Math.PI - 2 Math.PI) 始终为负值),但是由于 fetti.gravity始终为正值,因此到了某个临界点,y的值会不断增加。

我模拟了以下的坐标,由于为了让大家能明白这个轨迹,以下坐标轴和canvas中相反,数据我也做了相应的处理,进行了反方向处理。

用一个边上为10的正方形,实现轨迹。

const fetti = {
  "x": 445,
  "y": 541,
  "angle2D": 3 / 2 * Math.PI + 1 / 6 * Math.PI,
  "color": {r: 20, g: 30, b: 50},
  "tick": 0,
  "totalTicks": 200,
  "decay": 0.9,
  "gravity": 3,
  "velocity": 50
}
var animationFrame = null;
const update = () => {
  context.clearRect(0, 0, canvas.width, canvas.height);
  context.fillStyle = 'rgba(2, 255, 255, 1)';
  context.beginPath();
  fetti.x += Math.cos(fetti.angle2D) * fetti.velocity; // 第一个点
  fetti.y += Math.sin(fetti.angle2D) * fetti.velocity + fetti.gravity; // 第一个点

  var x1 = fetti.x;
  var y1 = fetti.y;

  var x2 = fetti.x;// 第二个点
  var y2 = fetti.y + 10; // 第二个点

  var x3 = x1 + 10;
  var y3 = y1 + 10;

  var x4 = fetti.x + 10;
  var y4 = fetti.y;

  fetti.velocity *= fetti.decay;

  context.moveTo(Math.floor(x1), Math.floor(y1));
  context.lineTo(Math.floor(x2), Math.floor(y2));
  context.lineTo(Math.floor(x3), Math.floor(y3));
  context.lineTo(Math.floor(x4), Math.floor(y4));

  context.closePath();
  context.fill();
  animationFrame = raf.frame(update);
} 

是不是除了颜色和形状,有那味了?

反转特效

那么如何实现让这个下落更加自然,会有一种飘落的感觉呢?

其实,他就是一直在做一个翻转特效.

将他们拆解就是在做绕着一个点的旋转运动,整个过程就是一边自我翻转一边按照运动轨迹进行移动。

实现这个特效,其实之前在实现正方形的时候提到过,实现一个正方形。满足以下三个点能实现一个平行四边形。

  • 知道一个点的位置
  • 知道一个角度
  • 知道一边边长

目前我能确定的有,一个点的位置很容易确定,就是我们的起始点,然后我们边长也知道,就差一个角度了,只要我们的角度不断变化,我们就能实现以上特效。

const update = () => {
  context.clearRect(0, 0, canvas.width, canvas.height);
  context.fillStyle = 'rgba(2, 255, 255, 1)';
  context.beginPath();

  fetti.velocity *= fetti.decay;
  fetti.tiltAngle += 0.1 // 不断给这个四边形变化角度

  var length = 10;

  var x1 = fetti.x;
  var y1 = fetti.y;

  var x2 = fetti.x + (length * Math.sin(fetti.tiltAngle));// 第二个点
  var y2 = fetti.y + (length * Math.cos(fetti.tiltAngle)); // 第二个点

  var x3 = x2 + 10;
  var y3 = y2;

  var x4 = fetti.x + length;
  var y4 = fetti.y;


  context.moveTo(Math.floor(x1), Math.floor(y1));
  context.lineTo(Math.floor(x2), Math.floor(y2));
  context.lineTo(Math.floor(x3), Math.floor(y3));
  context.lineTo(Math.floor(x4), Math.floor(y4));

  context.closePath();
  context.fill();
  animationFrame = raf.frame(update);
} 

这样我们就实现了以上的特效。

组合运动

然后把我们以上写的组合在一起就是一个完整的特效啦。

const update = () => {
  context.clearRect(0, 0, canvas.width, canvas.height);
  context.fillStyle = 'rgba(2, 255, 255, 1)';
  context.beginPath();
  fetti.x += Math.cos(fetti.angle2D) * fetti.velocity; // 第一个点
  fetti.y += Math.sin(fetti.angle2D) * fetti.velocity + fetti.gravity; // 第一个点

  fetti.velocity *= fetti.decay;
  fetti.tiltAngle += 0.1 // 不断给这个四边形变化角度

  var length = 10;

  var x1 = fetti.x;
  var y1 = fetti.y;

  var x2 = fetti.x + (length * Math.sin(fetti.tiltAngle));// 第二个点
  var y2 = fetti.y + (length * Math.cos(fetti.tiltAngle)); // 第二个点

  var x3 = x2 + 10;
  var y3 = y2;

  var x4 = fetti.x + length;
  var y4 = fetti.y;


  context.moveTo(Math.floor(x1), Math.floor(y1));
  context.lineTo(Math.floor(x2), Math.floor(y2));
  context.lineTo(Math.floor(x3), Math.floor(y3));
  context.lineTo(Math.floor(x4), Math.floor(y4));

  context.closePath();
  context.fill();
  animationFrame = raf.frame(update);
} 

最终形态

如果想要实现最后的状态,就差多个小块渐变消失以及随机颜色了!

设置多少帧消失,这里搞了两个变量totalTickstick,自定义来控制多少帧后小块消失。

至于多个小块,我们只需要搞一个 for 循环。

而随机颜色,搞了一个colors列表。

const colors = [
  '#26ccff',
  '#a25afd',
  '#ff5e7e',
  '#88ff5a',
  '#fcff42',
  '#ffa62d',
  '#ff36ff'
];
var arr = []
for (let i = 0; i < 20; i++) {
  arr.push({
    "x": 445,
    "y": 541,
    "velocity": (45 * 0.5) + (Math.random() * 20),
    "angle2D": 3 / 2 * Math.PI + Math.random() * 1 / 4 * Math.PI,
    "tiltAngle":  Math.random() * Math.PI,
    "color": hexToRgb(colors[Math.floor(Math.random() * 7)]),
    "shape": "square",
    "tick": 0,
    "totalTicks": 200,
    "decay": 0.9,
    "random": 0,
    "tiltSin": 0,
    "tiltCos": 0,
    "gravity": 3,
  })
} 

完整代码请看

https://github.com/hua1995116/node-demo/blob/master/confetti/完整demo.html

加点餐

实现多人对战形态的表情大战。在我们微信中表情的发送并不是单点的,而是多人形态,因此我们可以继续探索,利用 websocket 和多彩小块结合。

这里我们需要注意几个点。(由于篇幅原因就不对 websocket 展开讲解了,提一下实现要点)。

  • 我们可以通过一个 tag 来区分是历史消息还是实时消息
  • 区分是自己发出的消息,还是受到别人的消息,来改变五彩纸屑方向。
  • 只有为单个 🎉的时候才会进行动画。
  • 先进行放大缩小的动画,延迟200ms再出来特效
if(this.msg === '🎉' && this.status) {
        this.confetti = true;
        const rect = this.$refs.msg.querySelector('.msg-text').getBoundingClientRect();
        if(rect.left && rect.top) {
          setTimeout(() => {
            confetti({
              particleCount: r(100, 150),
              angle: this.isSelf ? 120 : 60,
              spread: r(45, 80),
              origin: {
                x: rect.left / window.innerWidth,
                y: rect.top / window.innerHeight
              }
            });
          }, 200)
        }
} 

更多探索

用 canvas 绘制非常非常多方块的时候,会比较卡顿,这个时候我们可以利用 web worker 来进行计算,从而提高性能,这个就请读者们自行探索啦,也可以看 canvas-confetti的源码~

最后

回看笔者往期高赞文章,也许能收获更多喔!

结语

❤️关注+点赞+收藏+评论+转发❤️,原创不易,鼓励笔者创作更好的文章

关注公众号秋风的笔记,一个专注于前端面试、工程化、开源的前端公众号

  • 关注后回复简历获取100+套的精美简历模板
  • 关注后回复好友拉你进技术交流群+面试交流群
  • 欢迎关注秋风的笔记
查看原文

赞 23 收藏 11 评论 0

蓝色的秋风 赞了文章 · 2月3日

50道CSS基础面试题(附答案)

1 介绍一下标准的CSS的盒子模型?与低版本IE的盒子模型有什么不同的?

标准盒子模型:宽度=内容的宽度(content)+ border + padding + margin
低版本IE盒子模型:宽度=内容宽度(content+border+padding)+ margin

2 box-sizing属性?

用来控制元素的盒子模型的解析模式,默认为content-box
context-box:W3C的标准盒子模型,设置元素的 height/width 属性指的是content部分的高/宽
border-box:IE传统盒子模型。设置元素的height/width属性指的是border + padding + content部分的高/宽

3 CSS选择器有哪些?哪些属性可以继承?

CSS选择符:id选择器(#myid)、类选择器(.myclassname)、标签选择器(div, h1, p)、相邻选择器(h1 + p)、子选择器(ul > li)、后代选择器(li a)、通配符选择器(*)、属性选择器(a[rel="external"])、伪类选择器(a:hover, li:nth-child)

可继承的属性:font-size, font-family, color

不可继承的样式:border, padding, margin, width, height

优先级(就近原则):!important > [ id > class > tag ]
!important 比内联优先级高

4 CSS优先级算法如何计算?

元素选择符: 1
class选择符: 10
id选择符:100
元素标签:1000

  1. !important声明的样式优先级最高,如果冲突再进行计算。
  2. 如果优先级相同,则选择最后出现的样式。
  3. 继承得到的样式的优先级最低。

5 CSS3新增伪类有那些?

p:first-of-type 选择属于其父元素的首个元素
p:last-of-type 选择属于其父元素的最后元素
p:only-of-type 选择属于其父元素唯一的元素
p:only-child 选择属于其父元素的唯一子元素
p:nth-child(2) 选择属于其父元素的第二个子元素
:enabled :disabled 表单控件的禁用状态。
:checked 单选框或复选框被选中。

6 如何居中div?如何居中一个浮动元素?如何让绝对定位的div居中?

div:

border: 1px solid red;
margin: 0 auto; 
height: 50px;
width: 80px;

浮动元素的上下左右居中:

border: 1px solid red;
float: left;
position: absolute;
width: 200px;
height: 100px;
left: 50%;
top: 50%;
margin: -50px 0 0 -100px; 

绝对定位的左右居中:

border: 1px solid black;
position: absolute;
width: 200px;
height: 100px;
margin: 0 auto;
left: 0;
right: 0; 

还有更加优雅的居中方式就是用flexbox,我以后会做整理。

7 display有哪些值?说明他们的作用?

inline(默认)--内联
none--隐藏
block--块显示
table--表格显示
list-item--项目列表
inline-block

8 position的值?

static(默认):按照正常文档流进行排列;
relative(相对定位):不脱离文档流,参考自身静态位置通过 top, bottom, left, right 定位;
absolute(绝对定位):参考距其最近一个不为static的父级元素通过top, bottom, left, right 定位;
fixed(固定定位):所固定的参照对像是可视窗口。

9 CSS3有哪些新特性?

  1. RGBA和透明度
  2. background-image background-origin(content-box/padding-box/border-box) background-size background-repeat
  3. word-wrap(对长的不可分割单词换行)word-wrap:break-word
  4. 文字阴影:text-shadow: 5px 5px 5px #FF0000;(水平阴影,垂直阴影,模糊距离,阴影颜色)
  5. font-face属性:定义自己的字体
  6. 圆角(边框半径):border-radius 属性用于创建圆角
  7. 边框图片:border-image: url(border.png) 30 30 round
  8. 盒阴影:box-shadow: 10px 10px 5px #888888
  9. 媒体查询:定义两套css,当浏览器的尺寸变化时会采用不同的属性

10 请解释一下CSS3的flexbox(弹性盒布局模型),以及适用场景?

该布局模型的目的是提供一种更加高效的方式来对容器中的条目进行布局、对齐和分配空间。在传统的布局方式中,block 布局是把块在垂直方向从上到下依次排列的;而 inline 布局则是在水平方向来排列。弹性盒布局并没有这样内在的方向限制,可以由开发人员自由操作。
试用场景:弹性布局适合于移动前端开发,在Android和ios上也完美支持。

11 用纯CSS创建一个三角形的原理是什么?

首先,需要把元素的宽度、高度设为0。然后设置边框样式。

width: 0;
height: 0;
border-top: 40px solid transparent;
border-left: 40px solid transparent;
border-right: 40px solid transparent;
border-bottom: 40px solid #ff0000;

12 一个满屏品字布局如何设计?

第一种真正的品字:

  1. 三块高宽是确定的;
  2. 上面那块用margin: 0 auto;居中;
  3. 下面两块用float或者inline-block不换行;
  4. 用margin调整位置使他们居中。

第二种全屏的品字布局:
上面的div设置成100%,下面的div分别宽50%,然后使用float或者inline使其不换行。

13 常见的兼容性问题?

  1. 不同浏览器的标签默认的margin和padding不一样。

    *{margin:0;padding:0;}

  2. IE6双边距bug:块属性标签float后,又有横行的margin情况下,在IE6显示margin比设置的大。hack:display:inline;将其转化为行内属性。
  3. 渐进识别的方式,从总体中逐渐排除局部。首先,巧妙的使用“9”这一标记,将IE浏览器从所有情况中分离出来。接着,再次使用“+”将IE8和IE7、IE6分离开来,这样IE8已经独立识别。

    {
    background-color:#f1ee18;/*所有识别*/
    .background-color:#00deff\9; /*IE6、7、8识别*/
    +background-color:#a200ff;/*IE6、7识别*/
    _background-color:#1e0bd1;/*IE6识别*/
    }
    
  4. 设置较小高度标签(一般小于10px),在IE6,IE7中高度超出自己设置高度。hack:给超出高度的标签设置overflow:hidden;或者设置行高line-height 小于你设置的高度。
  5. IE下,可以使用获取常规属性的方法来获取自定义属性,也可以使用getAttribute()获取自定义属性;Firefox下,只能使用getAttribute()获取自定义属性。解决方法:统一通过getAttribute()获取自定义属性。
  6. Chrome 中文界面下默认会将小于 12px 的文本强制按照 12px 显示,可通过加入 CSS 属性 -webkit-text-size-adjust: none; 解决。
  7. 超链接访问过后hover样式就不出现了,被点击访问过的超链接样式不再具有hover和active了。解决方法是改变CSS属性的排列顺序:L-V-H-A ( love hate ): a:link {} a:visited {} a:hover {} a:active {}

14 为什么要初始化CSS样式

因为浏览器的兼容问题,不同浏览器对有些标签的默认值是不同的,如果没对CSS初始化往往会出现浏览器之间的页面显示差异。

15 absolute的containing block计算方式跟正常流有什么不同?

无论属于哪种,都要先找到其祖先元素中最近的 position 值不为 static 的元素,然后再判断:

  1. 若此元素为 inline 元素,则 containing block 为能够包含这个元素生成的第一个和最后一个 inline box 的 padding box (除 margin, border 外的区域) 的最小矩形;
  2. 否则,则由这个祖先元素的 padding box 构成。

如果都找不到,则为 initial containing block。

补充:

  1. static(默认的)/relative:简单说就是它的父元素的内容框(即去掉padding的部分)
  2. absolute: 向上找最近的定位为absolute/relative的元素
  3. fixed: 它的containing block一律为根元素(html/body)

16 CSS里的visibility属性有个collapse属性值?在不同浏览器下以后什么区别?

当一个元素的visibility属性被设置成collapse值后,对于一般的元素,它的表现跟hidden是一样的。

  1. chrome中,使用collapse值和使用hidden没有区别。
  2. firefox,opera和IE,使用collapse值和使用display:none没有什么区别。

17 display:none与visibility:hidden的区别?

display:none 不显示对应的元素,在文档布局中不再分配空间(回流+重绘)
visibility:hidden 隐藏对应元素,在文档布局中仍保留原来的空间(重绘)

18 position跟display、overflow、float这些特性相互叠加后会怎么样?

display属性规定元素应该生成的框的类型;position属性规定元素的定位类型;float属性是一种布局方式,定义元素在哪个方向浮动。
类似于优先级机制:position:absolute/fixed优先级最高,有他们在时,float不起作用,display值需要调整。float 或者absolute定位的元素,只能是块元素或表格。

19 对BFC规范(块级格式化上下文:block formatting context)的理解?

BFC规定了内部的Block Box如何布局。
定位方案:

  1. 内部的Box会在垂直方向上一个接一个放置。
  2. Box垂直方向的距离由margin决定,属于同一个BFC的两个相邻Box的margin会发生重叠。
  3. 每个元素的margin box 的左边,与包含块border box的左边相接触。
  4. BFC的区域不会与float box重叠。
  5. BFC是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。
  6. 计算BFC的高度时,浮动元素也会参与计算。

满足下列条件之一就可触发BFC

  1. 根元素,即html
  2. float的值不为none(默认)
  3. overflow的值不为visible(默认)
  4. display的值为inline-block、table-cell、table-caption
  5. position的值为absolute或fixed

20 为什么会出现浮动和什么时候需要清除浮动?清除浮动的方式?

浮动元素碰到包含它的边框或者浮动元素的边框停留。由于浮动元素不在文档流中,所以文档流的块框表现得就像浮动框不存在一样。浮动元素会漂浮在文档流的块框上。
浮动带来的问题:

  1. 父元素的高度无法被撑开,影响与父元素同级的元素
  2. 与浮动元素同级的非浮动元素(内联元素)会跟随其后
  3. 若非第一个元素浮动,则该元素之前的元素也需要浮动,否则会影响页面显示的结构。

清除浮动的方式:

  1. 父级div定义height
  2. 最后一个浮动元素后加空div标签 并添加样式clear:both。
  3. 包含浮动元素的父标签添加样式overflow为hidden或auto。
  4. 父级div定义zoom

21 上下margin重合的问题

在重合元素外包裹一层容器,并触发该容器生成一个BFC。
例子:

<div class="aside"></div>
<div class="text">
    <div class="main"></div>
</div>
<!--下面是css代码-->
 .aside {
            margin-bottom: 100px;  
            width: 100px;
            height: 150px;
            background: #f66;
        }
        .main {
            margin-top: 100px;
            height: 200px;
            background: #fcc;
        }
         .text{
            /*盒子main的外面包一个div,通过改变此div的属性使两个盒子分属于两个不同的BFC,以此来阻止margin重叠*/
            overflow: hidden;  //此时已经触发了BFC属性。
        }

22设置元素浮动后,该元素的display值是多少?

自动变成display:block

23 移动端的布局用过媒体查询吗?

通过媒体查询可以为不同大小和尺寸的媒体定义不同的css,适应相应的设备的显示。

  1. <head>里边

    <link rel="stylesheet" type="text/css" href="xxx.css" media="only screen and (max-device-width:480px)">

  2. CSS : @media only screen and (max-device-width:480px) {/css样式/}

24 使用 CSS 预处理器吗?
Less sass

25 CSS优化、提高性能的方法有哪些?

  1. 避免过度约束
  2. 避免后代选择符
  3. 避免链式选择符
  4. 使用紧凑的语法
  5. 避免不必要的命名空间
  6. 避免不必要的重复
  7. 最好使用表示语义的名字。一个好的类名应该是描述他是什么而不是像什么
  8. 避免!important,可以选择其他选择器
  9. 尽可能的精简规则,你可以合并不同类里的重复规则

26 浏览器是怎样解析CSS选择器的?

CSS选择器的解析是从右向左解析的。若从左向右的匹配,发现不符合规则,需要进行回溯,会损失很多性能。若从右向左匹配,先找到所有的最右节点,对于每一个节点,向上寻找其父节点直到找到根元素或满足条件的匹配规则,则结束这个分支的遍历。两种匹配规则的性能差别很大,是因为从右向左的匹配在第一步就筛选掉了大量的不符合条件的最右节点(叶子节点),而从左向右的匹配规则的性能都浪费在了失败的查找上面。
而在 CSS 解析完毕后,需要将解析的结果与 DOM Tree 的内容一起进行分析建立一棵 Render Tree,最终用来进行绘图。在建立 Render Tree 时(WebKit 中的「Attachment」过程),浏览器就要为每个 DOM Tree 中的元素根据 CSS 的解析结果(Style Rules)来确定生成怎样的 Render Tree。

27 在网页中的应该使用奇数还是偶数的字体?为什么呢?

使用偶数字体。偶数字号相对更容易和 web 设计的其他部分构成比例关系。Windows 自带的点阵宋体(中易宋体)从 Vista 开始只提供 12、14、16 px 这三个大小的点阵,而 13、15、17 px时用的是小一号的点。(即每个字占的空间大了 1 px,但点阵没变),于是略显稀疏。

28 margin和padding分别适合什么场景使用?

何时使用margin:

  1. 需要在border外侧添加空白
  2. 空白处不需要背景色
  3. 上下相连的两个盒子之间的空白,需要相互抵消时。

何时使用padding:

  1. 需要在border内侧添加空白
  2. 空白处需要背景颜色
  3. 上下相连的两个盒子的空白,希望为两者之和。

兼容性的问题:在IE5 IE6中,为float的盒子指定margin时,左侧的margin可能会变成两倍的宽度。通过改变padding或者指定盒子的display:inline解决。

29 元素竖向的百分比设定是相对于容器的高度吗?

当按百分比设定一个元素的宽度时,它是相对于父容器的宽度计算的,但是,对于一些表示竖向距离的属性,例如 padding-top , padding-bottom , margin-top , margin-bottom 等,当按百分比设定它们时,依据的也是父容器的宽度,而不是高度。

30 全屏滚动的原理是什么?用到了CSS的哪些属性?

  1. 原理:有点类似于轮播,整体的元素一直排列下去,假设有5个需要展示的全屏页面,那么高度是500%,只是展示100%,剩下的可以通过transform进行y轴定位,也可以通过margin-top实现
  2. overflow:hidden;transition:all 1000ms ease;

31 什么是响应式设计?响应式设计的基本原理是什么?如何兼容低版本的IE?

响应式网站设计(Responsive Web design)是一个网站能够兼容多个终端,而不是为每一个终端做一个特定的版本。
基本原理是通过媒体查询检测不同的设备屏幕尺寸做处理。
页面头部必须有meta声明的viewport。

<meta name=’viewport’ content=”width=device-width, initial-scale=1. maximum-scale=1,user-scalable=no”>

32 视差滚动效果?

视差滚动(Parallax Scrolling)通过在网页向下滚动的时候,控制背景的移动速度比前景的移动速度慢来创建出令人惊叹的3D效果。

  1. CSS3实现
    优点:开发时间短、性能和开发效率比较好,缺点是不能兼容到低版本的浏览器
  2. jQuery实现
    通过控制不同层滚动速度,计算每一层的时间,控制滚动效果。
    优点:能兼容到各个版本的,效果可控性好
    缺点:开发起来对制作者要求高
  3. 插件实现方式
    例如:parallax-scrolling,兼容性十分好

33 ::before 和 :after中双冒号和单冒号有什么区别?解释一下这2个伪元素的作用

  1. 单冒号(:)用于CSS3伪类,双冒号(::)用于CSS3伪元素。
  2. ::before就是以一个子元素的存在,定义在元素主体内容之前的一个伪元素。并不存在于dom之中,只存在在页面之中。

:before 和 :after 这两个伪元素,是在CSS2.1里新出现的。起初,伪元素的前缀使用的是单冒号语法,但随着Web的进化,在CSS3的规范里,伪元素的语法被修改成使用双冒号,成为::before ::after

34 你对line-height是如何理解的?

行高是指一行文字的高度,具体说是两行文字间基线的距离。CSS中起高度作用的是height和line-height,没有定义height属性,最终其表现作用一定是line-height。
单行文本垂直居中:把line-height值设置为height一样大小的值可以实现单行文字的垂直居中,其实也可以把height删除。
多行文本垂直居中:需要设置display属性为inline-block。

35 怎么让Chrome支持小于12px 的文字?

p{font-size:10px;-webkit-transform:scale(0.8);} //0.8是缩放比例

36 让页面里的字体变清晰,变细用CSS怎么做?

-webkit-font-smoothing在window系统下没有起作用,但是在IOS设备上起作用-webkit-font-smoothing:antialiased是最佳的,灰度平滑。

37 position:fixed;在android下无效怎么处理?

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no"/>

38 如果需要手动写动画,你认为最小时间间隔是多久,为什么?
多数显示器默认频率是60Hz,即1秒刷新60次,所以理论上最小间隔为1/60*1000ms = 16.7ms。

39 li与li之间有看不见的空白间隔是什么原因引起的?有什么解决办法?

行框的排列会受到中间空白(回车空格)等的影响,因为空格也属于字符,这些空白也会被应用样式,占据空间,所以会有间隔,把字符大小设为0,就没有空格了。
解决方法:

  1. 可以将<li>代码全部写在一排
  2. 浮动li中float:left
  3. 在ul中用font-size:0(谷歌不支持);可以使用letter-space:-3px

40 display:inline-block 什么时候会显示间隙?

  1. 有空格时候会有间隙 解决:移除空格
  2. margin正值的时候 解决:margin使用负值
  3. 使用font-size时候 解决:font-size:0、letter-spacing、word-spacing

41 有一个高度自适应的div,里面有两个div,一个高度100px,希望另一个填满剩下的高度

外层div使用position:relative;高度要求自适应的div使用position: absolute; top: 100px; bottom: 0; left: 0

42 png、jpg、gif 这些图片格式解释一下,分别什么时候用。有没有了解过webp?

  1. png是便携式网络图片(Portable Network Graphics)是一种无损数据压缩位图文件格式.优点是:压缩比高,色彩好。 大多数地方都可以用。
  2. jpg是一种针对相片使用的一种失真压缩方法,是一种破坏性的压缩,在色调及颜色平滑变化做的不错。在www上,被用来储存和传输照片的格式。
  3. gif是一种位图文件格式,以8位色重现真色彩的图像。可以实现动画效果.
  4. webp格式是谷歌在2010年推出的图片格式,压缩率只有jpg的2/3,大小比png小了45%。缺点是压缩的时间更久了,兼容性不好,目前谷歌和opera支持。

43 style标签写在body后与body前有什么区别?

页面加载自上而下 当然是先加载样式。
写在body标签后由于浏览器以逐行方式对HTML文档进行解析,当解析到写在尾部的样式表(外联或写在style标签)会导致浏览器停止之前的渲染,等待加载且解析样式表完成之后重新渲染,在windows的IE下可能会出现FOUC现象(即样式失效导致的页面闪烁问题)

44 CSS属性overflow属性定义溢出元素内容区的内容会如何处理?

参数是scroll时候,必会出现滚动条。
参数是auto时候,子元素内容大于父元素时出现滚动条。
参数是visible时候,溢出的内容出现在父元素之外。
参数是hidden时候,溢出隐藏。

45 阐述一下CSS Sprites

将一个页面涉及到的所有图片都包含到一张大图中去,然后利用CSS的 background-image,background- repeat,background-position 的组合进行背景定位。利用CSS Sprites能很好地减少网页的http请求,从而大大的提高页面的性能;CSS Sprites能减少图片的字节。

持续更新中...

查看原文

赞 320 收藏 760 评论 55

蓝色的秋风 赞了文章 · 1月19日

原来地图导航结合WebAR技术还能这么玩

本文探索在Web前端实现AR导航效果的前沿技术和难点。

1. AR简介

增强现实(Augmented Reality,简称AR):是一种实时地计算摄影机影像的位置及角度并加上相应图像、视频、3D模型的技术,这种技术的目标是在屏幕上把虚拟世界套在现实世界并进行互动。

一般在web中实现AR效果的主要步骤如下:

  1. 获取视频源
  2. 识别marker
  3. 叠加虚拟物体
  4. 显示最终画面

AR导航比较特殊的地方是,它并非通过识别marker来确定虚拟物体的叠加位置,而是通过定位将虚拟和现实联系在一起,主要步骤如下:

  1. 获取视频源
  2. 坐标系转换:

    1. 获取设备和路径的绝对定位
    2. 计算路径中各标记点与设备间的相对定位
    3. 在设备坐标系中绘制标记点
  3. 3D图像与视频叠加
  4. 更新定位和设备方向,控制Three.js中的相机移动

2. 技术难点

如上文所述AR导航的主要步骤,其中难点在于:

  1. 兼容性问题
  2. WebGL三维作图
  3. 定位的精确度和轨迹优化
  4. 虚拟和现实单位尺度的映射

2.1 兼容性问题:

不同设备不同操作系统以及不同浏览器带来的兼容性问题主要体现在对获取视频流和获取设备陀螺仪信息的支持上。

2.1.1 获取视频流

  1. Navigator API兼容处理

    navigator.getUserMedia()已不推荐使用,目前新标准采用navigator.mediaDevices.getUserMedia()。可是不同浏览器对新方法的支持程度不同,需要进行判断和处理。同时,如果采用旧方法,在不同浏览器中方法名称也不尽相同,比如webkitGetUserMedia

//不支持mediaDevices属性
    if (navigator.mediaDevices === undefined) {
      navigator.mediaDevices = {};
    }

//不支持mediaDevices.getUserMedia
    if (navigator.mediaDevices.getUserMedia === undefined) {
        navigator.mediaDevices.getUserMedia = function(constraints) {
            var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;

            if(!getUserMedia) {
                return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
            }

            return new Promise(function(resolve, reject) {
                getUserMedia.call(navigator, constraints, resolve, reject);
            });
        }
    }
  1. 参数兼容处理

    getUserMedia接收一个MediaStreamConstraints类型的参数,该参数包含两个成员videoaudio

var constraints = {
        audio: true,
        video: {
            width: { 
                min: 1024,
                ideal: 1280,
                max: 1920
            },
            height: 720,
            frameRate: {
                ideal: 10,
                max: 15
            },
            facingMode: "user" // user/environment,设置前后摄像头
        }
    }

在使用WebAR导航时,需要调取后置摄像头,然而facingMode参数目前只有Firefox和Chrome部分支持,对于其他浏览器(微信、手Q、QQ浏览器)需要另一个参数optional.sourceId,传入设备媒体源的id。经测试,该方法在不同设备不同版本号的微信和手Q上表现有差异。

if(MediaStreamTrack.getSources) {
        MediaStreamTrack.getSources(function (sourceInfos) {
            for (var i = 0; i != sourceInfos.length; ++i) {
                var sourceInfo = sourceInfos[i];
                //这里会遍历audio,video,所以要加以区分  
                if (sourceInfo.kind === 'video') {  
                    exArray.push(sourceInfo.id);  
                }  
            }
            constraints = { 
                video: {  
                    optional: [{  
                        sourceId: exArray[1] //0为前置摄像头,1为后置
                    }]  
                }
            };
        });
    } else {
        constraints = { 
            video: {
                facingMode: {
                    exact: 'environment'
                }
            }
        });
    }
  1. 操作系统的兼容性问题

    由于苹果的安全机制问题,iOS设备任何浏览器都不支持getUserMedia()。所以无法在iOS系统上实现WebAR导航。

  2. 协议

    出于安全考虑,Chrome47之后只支持HTTPS页面获取视频源。

2.1.2 获取设备转动角度

设备的转动角度代表了用户的视角,也是连接虚拟和现实的重要参数。HTML5提供DeviceOrientation API可以实时获取设备的旋转角度参数。通过监听deviceorientation事件,返回DeviceOrientationEvent对象。

{
    absolute: [boolean] 是否为绝对转动值
    alpha: [0-360]
    beta: [-180-180]
    gamma: [-90-90]
}

其中alpha、beta、gamma是我们想要获取的角度,它们各自的意义可以参照下图和参考文章:

image
陀螺仪的基本知识

然而iOS系统的webkit内核浏览器中,该对象还包括webkitCompassHeading成员,其值为设备与正北方向的偏离角度。同时iOS系统的浏览器中,alpha并非绝对角度,而是以开始监听事件时的角度为零点。

Android系统中,我们可以使用-alpha得到设备与正北方的角度,但是就目前的测试情况看来,该值并不稳定。所以在测试Demo中加入了手动校正alpha值的过程,在导航开始前将设备朝向正北方来获取绝对0度,虽然不严谨但效果还不错。

image

2.2 WebGL三维作图

WebGL是在浏览器中实现三维效果的一套规范,AR导航需要绘制出不同距离不同角度的标记点,就需要三维效果以适应真实场景视频流。然而WebGL原生的接口非常复杂,Three.js是一个基于WebGL的库,它对一些原生的方法进行了简化封装,使我们能够更方便地进行编程。

Three.js中有三个主要概念:

  1. 场景(scene):物体的容器,我们要绘制标记点就是在场景中添加指定坐标和大小的球体
  2. 相机(camera):模拟人的眼睛,决定了呈现哪个角度哪个部分的场景,在AR导航中,我们主要通过相机的移动和转动来模拟设备的移动和转动
  3. 渲染器(renderer):设置画布,将相机拍摄的场景呈现在web页面上

在AR导航的代码中,我对Three.js的创建过程进行了封装,只需传入DOM元素(一般为<div>,作为容器)和参数,自动创建三大组件,并提供了Three.addObjectThree.renderThree等接口方法用于在场景中添加/删除物体或更新渲染等。

function Three(cSelector, options) {
    var container = document.querySelector(cSelector);
    // 创建场景
    var scene = new THREE.Scene();
    // 创建相机
    var camera = new THREE.PerspectiveCamera(options.camera.fov, options.camera.aspect, options.camera.near, options.camera.far);
    // 创建渲染器
    var renderer = new THREE.WebGLRenderer({
        alpha: true
    });
    // 设置相机转动控制器
    var oriControls = new THREE.DeviceOrientationControls(camera);
    // 设置场景大小,并添加到页面中
    renderer.setSize(container.clientWidth, container.clientHeight);
    renderer.setClearColor(0xFFFFFF, 0.0);
    container.appendChild(renderer.domElement);

    // 暴露在外的成员
    this.main = {
        scene: scene,
        camera: camera,
        renderer: renderer,
        oriControls: oriControls,
    }
    this.objects = [];
    this.options = options;
}
Three.prototype.addObject = function(type, options) {...} // 向场景中添加物体,type支持sphere/cube/cone
Three.prototype.popObject = function() {...} // 删除场景中的物体
Three.prototype.setCameraPos = function(position) {...} // 设置相机位置
Three.prototype.renderThree = function(render) {...} // 渲染更新,render为回调函数
Three.prototype.setAlphaOffset = function(offset) {..} // 设置校正alpha的偏离角度

在控制相机的转动上,我使用了DeviceOrientationControls,它是Three.js官方提供的相机跟随设备转动的控制器,实现对deviceorientation的侦听和对DeviceOrientationEvent的欧拉角处理,并控制相机的转动角度。只需在渲染更新时调用一下update方法:

three.renderThree(function(objects, main) {
    animate();
    function animate() {
        window.requestAnimationFrame(animate);
        main.oriControls.update();
        main.renderer.render(main.scene, main.camera);
    }
});

2.3 定位的精确度和轨迹优化

我们的调研中目前有三种获取定位的方案:原生navigator.geolocation接口,腾讯前端定位组件,微信JS-SDK地理位置接口:

  1. 原生接口

    navigator.geolocation接口提供了getCurrentPositionwatchPosition两个方法用于获取当前定位和监听位置改变。经过测试,Android系统中watchPosition更新频率低,而iOS中更新频率高,但抖动严重。

  2. 前端定位组件

    使用前端定位组件需要引入JS模块(https://3gimg.qq.com/lightmap/components/geolocation/geolocation.min.js),通过 qq.maps.Geolocation(key, referer)构造对象,也提供getLocationwatchPosition两个方法。经过测试,在X5内核的浏览器(包括微信、手Q)中,定位组件比原生接口定位更加准确,更新频率较高。

  3. 微信JS-SDK地理位置接口

    使用微信JS-SDK接口,我们可以调用室内定位达到更高的精度,但是需要绑定公众号,只能在微信中使用,仅提供getLocation方法,暂时不考虑。

    综上所述,我们主要考虑在X5内核浏览器中的实现,所以选用腾讯前端定位组件获取定位。但是在测试中仍然暴露出了定位不准确的问题:

    1. 定位不准导致虚拟物体与现实无法准确叠加
    2. 定位的抖动导致虚拟标记点跟随抖动,移动视觉效果不够平稳

针对该问题,我设计了优化轨迹的方法,进行定位去噪、确定初始中心点、根据路径吸附等操作,以实现移动时的变化效果更加平稳且准确。

2.3.1 定位去噪

我们通过getLocationwatchPosition方法获取到的定位数据包含如下信息:

{
    accuracy: 65,
    lat: 39.98333,
    lng: 116.30133
    ...
}

其中accuracy表示定位精度,该值越低表示定位越精确。假设定位精度在固定的设备上服从正态分布(准确来说应该是正偏态分布),统计整条轨迹点定位精度的均值mean和标准差stdev,将轨迹中定位精度大于mean + (1~2) * stdev的点过滤掉。或者采用箱型图的方法去除噪声点。

2.3.2 初始点确定

初始点非常重要,若初始点偏离,则路线不准确、虚拟现实无法重叠、无法获取到正确的移动路线。测试中我发现定位开始时获得的定位点大多不太准确,所以需要一段时间来确定初始点。

定位开始,设置N秒用以获取初始定位。N秒钟获取到的定位去噪之后形成一个序列track_denoise = [ loc0, loc1, loc2...],对该序列中的每一个点计算其到其他点的距离之和,并加上自身的定位精度,得到一个中心衡量值,然后取衡量值最小的点为起始点。

image

2.3.3 基于路线的定位校正

基于设备始终跟随规划路线进行移动的假设,可以将定位点吸附到规划路线上以防止3D图像的抖动。

如下图所示,以定位点到线段的映射点作为校正点。路线线段的选择依据如下:

  1. 初始状态:以起始点与第二路线点之间的线段为当前线段,cur = 0; P_cur = P[cur];
  2. 在第N条线段上移动时,若映射长度(映射点与线段起点的距离)为负,校正点取当前线段的起点,线路回退至上一线段,cur = N - 1; P_cur = P[cur];;若映射长度大于线段长度,则校正点取当前线段的终点,线路前进至下一线段,cur = N + 1; P_cur = P[cur];
  3. 若当前线段与下一线段的有效范围有重叠区域(如下图绿色阴影区),则需判断定位点到两条线段的距离,以较短的为准,确定校正点和线路选择。

image

2.4 虚拟和现实的单位长度映射

WebGL中的单位长度与现实世界的单位长度并没有确定的映射关系,暂时还无法准确进行映射。通过测试,暂且选择1(米):15(WebGL单位长度)。

3. demo演示

演示视频:WebAR技术探索-导航中的应用

对地图感兴趣的开发者,欢迎登录腾讯位置服务体验~

以下内容转载自多多洛爱学习的文章《WebAR技术探索-导航中的应用》
作者:多多洛爱学习
链接:https://juejin.im/post/5c24252b6fb9a049d975411a
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
查看原文

赞 5 收藏 4 评论 0

蓝色的秋风 关注了用户 · 1月19日

腾讯位置服务 @tengxunweizhifuwu

立足生态,连接未来

关注 29

蓝色的秋风 发布了文章 · 1月14日

2020 全球 JS 调查报告新鲜出炉

完整报告地址: https://2020.stateofjs.com/zh-Hans/
润色/翻译: 蓝色的秋风(github/hua1995116)

千呼万唤的全球2020的JS报告终于出来了。顺便附上2020全球CSS报告地址 2020年度全球CSS报告新鲜出炉

image-20210114001259007

我们来看看这一个糟糕却又不平凡的一年,JS发生了什么样的变化。

image-20210114001739976

尽管2020年很糟糕,但 JavaScript 作为一个整体仍然设法向前发展。随着语言本身的不断改进,得益于诸如可选链操作符空值合并操作符并等新特性,TypeScript静态类型的普及更是将JS带到了一个全新的高度。

在框架方面,就在我们认为一切都已解决的时候,Svelte 横空出世以全新方式给前端注入新的血液。 在多年的webpack统治下,甚至构建工具也显示出新活动的迹象。

但是这次的区别是,相对而言,“老”后卫什么都没走。 Svelte和Snowpack很棒,但是React和webpack也很棒。 可以肯定的是,它们最终也会成为JavaScript大流氓的牺牲品,但是不会持续很多年。

所以,让我们享受我们所拥有的: 一个不断变得更好的伟大的生态系统!

访问对象统计

采样对象一共为 20744 位开发者。

image-20210114003014449

特性

虽然大多数受访者都知道调查中提到的大多数JavaScript特性,但很多人还没有真正使用它们。

这图表显示了按类别分组的所有特性的不同采用率。外圈的大小对应于了解某项功能的用户总数,而内圈则代表实际使用过该功能的用户。

image-20210114003419236

技术现状

2016年 - 2020年 趋势图

每条线从2016年到2020年(粗部为2020)。纵轴越高,表示一项技术被更多的人使用,横轴越大,表示有更多的用户想要学习,或者曾经使用过,还会再次使用。

image-20210114004041187

可以看出随着年限的的增长。webpack、Express、TypeScript、Jest、React 可以说是非常强势了。

风味(Flavors)

image-20210114011042569

可以看出 TypeScript 依旧独领风骚,其次就是 Elm ,但是 PureScript 也是一个值得关注的增强类型语言。

image-20210114004722545

对 TypeScript 的熟悉度一片叫好。

其他工具

image-20210114004757675

前端框架

image-20210114011217904

正如开头所说,svelte 的出现真的是对前端行业的冲击,原以为三大框架(React、Vue.js、Angular)包揽所有的时候,它出现了,一度成为了第四名(使用量),但是从兴趣度和满意度来看,它未来的潜力不可估量。

兴趣度

image-20210114011448248

满意度

image-20210114011511595

数据层

image-20210114011556857

使用排名比较高的状态管理依旧是Redux、Vuex、Mobx。 数据管理为 GraphQL 和 Apollo,并且 XState 横空出世。

其他工具

image-20210114005333559

后端框架

image-20210114011713944

Express 依旧是统治地位,而 Next 和 Nuxt 这些服务端渲染的框架也逐渐成为大家的所选的框架。

其他工具

image-20210114005400642

测试框架

image-20210114011830965

Jest和 Mocha 在使用量上依旧是统治地位,但是新增了 Testing Libray 很强劲。

以下是满意度排行。

image-20210114005427559

什么是 Testing Library ?用于 DOM 和 UI 组件测试的一系列工具,主要 API 包含 DOM 查询,更可以和其他测试工具(jest、cypress)配合,用于更多场景(react、vue、svelte)。而它是 React 的官方推荐。

我们推荐使用 React Testing Library,它使得针对组件编写测试用例就像终端用户在使用它一样方便。

----摘自 React 官网(https://zh-hans.reactjs.org/docs/test-utils.html)

打包工具

image-20210114011945951

虽然短时间内 webpack 使用量还处于霸主地位,这一年打包工具的发生了巨大的变化。

以下为满意度

image-20210114010039881

可以说这里发生了天翻地覆的变化。从 Parcel 到 Snowpack ,再到后来的 esbuild ,每一个都是打包的好手,至于 Vite 为什么没有在其中,我猜想,Vite 最开始只是为了解决 Vue 单个框架的方向,受众面不够广泛(现在它已经支持了多种框架的打包了)。

放张图来看看这些 bundleless 工具的速度吧。

image-20210114010649085

其他工具

image-20210114010412943

移动和桌面端

image-20210114012121186

Electron 依旧是桌面端的第一选择, Cordova 和 React Native 也是移动跨端的热门选择。但是新出的 Capacitor 值得关注。

其他工具

常用的工具函数库有?

image-20210114012305700

其他工具函数库

image-20210114012350566

JavaScript 运行时选择

image-20210114012435704

经常使用那(些)文字編輯器?

image-20210114012456227

常用用于开发的浏览器有哪些?

image-20210114012519560

资料

常用的 blog 和杂志?

image-20210114012556370

关注了哪些网站和课程?

image-20210114012616128

最后

如果我的文章有帮助到你,希望你也能帮助我,欢迎关注我的微信公众号 秋风的笔记,回复好友 二次,可加微信并且加入交流群,秋风的笔记 将一直陪伴你的左右。

image

查看原文

赞 11 收藏 4 评论 5

认证与成就

  • 获得 548 次点赞
  • 获得 4 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 4 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

  • webchat

    Websocket project based on vue(基于vue2.0的实时聊天项目)

注册于 2017-11-12
个人主页被 8.7k 人浏览