2016前端代码总结

  1. 使用gulp来开发自动化。在开发中,咱们会遇到不少重复性的工做,好比更新代码后刷新浏览器、压缩图片、压缩js、编译sass等等。gulp可使这些重复性的工做都帮你干了。gulp的使用能够参见gulp官网。 贴出下我使用的gulp脚本(注释不少,一目了然)。
    var gulp = require('gulp'); // sass 插件 var sass = require('gulp-sass'); // 自动同步浏览器插件 var browserSync = require('browser-sync'); // 合并文件的插件 var useref = require('gulp-useref'); // 压缩js插件 var uglify = require('gulp-uglify'); var gulpIf = require('gulp-if'); // 压缩css插件 var cssnano = require('gulp-cssnano'); // 压缩图片插件 var imagemin = require('gulp-imagemin'); // 压缩png图片的插件 var pngquant = require('imagemin-pngquant'); // 缓存插件,能够加快编译速度 var cache = require('gulp-cache'); // 删除文件插件 var del = require('del'); // 同步运行任务插件 var runSequence = require('run-sequence'); // 给css3属性添加浏览器前缀插件 var autoprefixer = require('gulp-autoprefixer'); // sourcemap 插件 var sourcemaps = require('gulp-sourcemaps'); var lazypipe = require('lazypipe'); // 合成sprite图片插件 var spritesmith = require('gulp.spritesmith'); var imageminOptipng = require('imagemin-optipng'); // 编译sass文件,添加css3属性浏览器前缀,reload 浏览器 gulp.task('sass', function () { return gulp.src('./src/scss/**/*.scss') .pipe(sass()) .pipe(autoprefixer()) .pipe(gulp.dest('./src/css')) .pipe(browserSync.reload({stream: true})); }); // 自动更新浏览器任务 gulp.task('browserSync', function () { browserSync.init({ server: { baseDir: 'src' } }) }); // 合并文件任务 // 在html设置须要合并的文件: // <!--build:js js/flexible.min.js --> // <script src="js/flexible_css.js"></script> // <script src="js/flexible.js"></script> // <!-- endbuild--> // 执行任务后,会编译成 : <script src="js/flexible.min.js"></script> // 同时会把 flexible_css.js 和 flexible.js 合并成 flexible.min.js gulp.task('useref', function () { return gulp.src('./src/*.html') .pipe(useref({}, lazypipe().pipe(sourcemaps.init, { loadMaps: true }))) .pipe(gulpIf('*.js', uglify())) .pipe(gulpIf('*.css', cssnano())) .pipe(sourcemaps.write('maps')) .pipe(gulp.dest('dist')); }); // 图片压缩任务 gulp.task('images', function () { return gulp.src('./src/img/**/*.+(png|jpg|gif|svg)') .pipe(imagemin({ progressive: true, svgoPlugins: [{removeViewBox: false}], use: [pngquant()] })) .pipe(gulp.dest('dist/img')); }); // 合并sprite图任务 gulp.task('sprite', function () { var spriteData = gulp.src('./src/img/sprite/**/*.png') .pipe(spritesmith({ imgName: 'sprite.png', cssName: 'sprite.scss', imgPath: '../img/sprite/sprite.png', cssFormat: 'scss', padding: 10 })); return spriteData.pipe(gulp.dest('./src/img/sprite/')) }); // 删除build目录 gulp.task('clean:dist', function () { return del.sync('dist'); }); // 清除缓存 gulp.task('cache:clear', function (cb) { return cache.clearAll(cb) }); // 监控任务,当有sass文件,html文件,js文件改动的时候,刷新浏览器 gulp.task('watch', ['browserSync', 'sass'], function () { gulp.watch('./src/scss/**/*.scss', ['sass']); gulp.watch('./src/*.html', browserSync.reload); gulp.watch('./src/js/**/*.js', browserSync.reload); }); // 构建最终输出文件 gulp.task('build', function (callback) { runSequence('clean:dist', ['sass', 'useref', 'images', 'fonts'], callback); }); // gulp 默认执行任务 gulp.task('default', function (callback) { runSequence(['sass', 'browserSync', 'watch'], callback); });

2.在开发移动端页面的时候,咱们须要兼容各类机型,iphone的机型相对来讲比较少,可是android的机型倒是多种多样,若是按照之前pc上开发页面的经验使用px来开发,确定会遇到各类兼容问题。虽然能够用media query来适配,可是这种适配将是一个很是繁琐的事情。那有没有更好的解决办法呢?固然是有的。在这里推荐淘宝的可伸缩布局方案lib-flexible
实现原理见: https://github.com/amfe/article/issues/17
须要注意的地方是: 在设置字体的时候须要根据dpr来调整字体大小(若是不设置会致使dpr高的手机由于缩放系数小而致使文字在手机上看起来很小)。以下代码所示:javascript

[data-dpr="1"] .preloader,[data-dpr="1"] .swiper-slide { font-size: 18px; } [data-dpr="2"] .preloader,[data-dpr="2"] .swiper-slide { font-size: 36px; } [data-dpr="2.5"] .preloader,[data-dpr="2.5"] .swiper-slide { font-size: 45px; } [data-dpr="2.75"] .preloader,[data-dpr="2.75"] .swiper-slide { font-size: 49px; } [data-dpr="3"] .preloader,[data-dpr="3"] .swiper-slide { font-size: 64px; } [data-dpr="4"] .preloader,[data-dpr="4"] .swiper-slide { font-size: 72px; }

3.为了更快的呈现页面,页面使用到的图片第一时间并不加载,而是在预加载界面才加载图片,固然同时也能够加载js和其余多媒体文件等。你们能够在网上找到一些预加载的开源组件,或者本身写一个预加载的组件。php

4.为了减小http请求数,能够把一些小的图片合并成一张雪碧图。默认spritesmith 生成的雪碧图代码是经过像素来定位的。可是咱们页面使用的rem。若是使用默认生成的雪碧图代码会致使图片显示并不完整。解决办法是经过background-position 百分比来实现。具体实现原理参见:移动端适配之雪碧图(sprite)背景图片定位
本身写了一个sass方法来把spritesmith生成的sass代码转换为background-position的实现。以下:css

//spritesmith 生成的sprite.sass,主要是须要获取到sprite图片中各图片的大小,用来计算background-position的值。大概以下代码所示: $cloud-b: (686px, 0px, -686px, 0px, 800px, 306px, 1486px, 1173px, '../img/sprite/sprite.png', 'cloud-b', ); // sass方法 $base: 72px; @function rem($size) { $remSize: $size / $base; @return #{$remSize}rem; } @mixin bgPostion($sprite){ $iconX:nth($sprite, 1); $spriteWidth:nth($sprite, 7); $iconWidth:nth($sprite, 5); $iconY:nth($sprite, 2); $spriteHeight:nth($sprite, 8); $iconHeight:nth($sprite, 6); $x:0; $y:0; @if $iconX != 0{ $x: ($iconX / ($spriteWidth - $iconWidth)) * 100%; } @if $iconY != 0{ $y: ($iconY / ($spriteHeight - $iconHeight)) * 100%; } background-position: ( $x $y ); } @mixin bg($sprite){ $sprite-width:nth($sprite, 7); $sprite-height:nth($sprite, 8); background: transparent; background-repeat: no-repeat; background-size: rem($sprite-width), rem($sprite-height); width: rem(nth($sprite, 5)); height: rem(nth($sprite, 6)); @include bgPostion($sprite); }

经过使用@include bg($cloud-b); 就能够引入sprite图片中相应的图片了。html

注意点: 在默认生成的sprite图片中各个小图片之间是没有间隔的。这致使使用上面的方法的时候在部分机型上会多显示1像素旁边图片的边框。解决办法是在生成sprite图片的时候参数设置padding值:java

gulp.task('sprite', function () { var spriteData = gulp.src('./src/img/sprite/**/*.png') .pipe(spritesmith({ imgName: 'sprite.png', cssName: 'sprite.scss', imgPath: '../img/sprite/sprite.png', cssFormat: 'scss', padding: 10 })); return spriteData.pipe(gulp.dest('./src/img/sprite/')) });

在使用帧动画sprite图的时候,能够设置下图片排列算法,好比说横向排练,这样在使用的时候也比较方便。algorithm: 'left-right',android

5.在实现吹风的动画时,具体请看报告第三页,使用了svg来实现。主要是使用path的 stroke-dasharray 和stroke-dashoffset属性。原理能够参考帅气的SVG路径描边动画 (path animation) 实战应用](https://segmentfault.com/a/1190000007811310)
不过在实现的时候,咱们不仅仅须要风出现也须要风消失。实现的代码以下:css3

.cls-wind{ // 省略其余代码 stroke-dasharray: 100px; stroke-dashoffset: 120px; animation: winds 2s ease infinite; } @keyframes winds{ from{ stroke-dashoffset: 120px; } 50%{ stroke-dashoffset: 0; } to{ stroke-dashoffset: -90px; } }

注意点: 在使用AI或者PS生成svg图像的时候,生成的文件会有不少多余的信息。能够利用svgo 来处理多余的信息,图像的文件尺寸会减小不少。在这也提一下图片压缩,移动端流量是很宝贵的,图片的尺寸在保证效果的状况下越小越好,可是我在使用过程当中发现imagemin 的压缩效果并非很是理想,虽然能够压缩一点,可是效果不明显。后面使用tinypng 压缩对比的时候,发现tinypng的压缩效果很是好,通常都能压缩个50%的大小,而且压缩后的图片在手机上的表现肉眼几乎看不出来。因此,我的建议在正式发布的时候,使用tinypng把你须要使用到的图片都压缩一遍。git

6.在使用css3动画的时候,咱们应该尽可能避免浏览器的reflow,reflow会针对整个页面进行重排,比较耗费性能。在实现报告中报告内容下拉的效果时,一开始使用的变换元素的height来实现。代码大概以下:github

@keyframes conten-action{ from{ height:0; } to{ height:5rem; } }

可是这样在一些低端的机型上表现不是很好。后面换成经过变换background-size 来实现,能够明显的感受到在那些低端的机型上动画流畅了不少。代码大概以下:web

@keyframes content-action{ from{ background-size: 100% 0%; opacity: 0; } 20%{ background-size: 100% 20%; opacity: 0; } to{ background-size: 100% 100%; opacity: 1; } }

固然css3的动画性能优化还有不少其余方面能够探索。我这就只记录我碰到的状况了。

7.在报告最后一页,会有一个火箭发射的效果。一开始想使用css3来实现,后面讨论说使用css3工做量太大了,可使用视频来播放这个动画,如今已经有不少h5页面是用视频来实现的,说明视频方案已是很成熟了。
咱们目前只支持微信端,这里说明的状况都是针对微信的状况。
如今微信都已经支持了video的playsinline属性,同时放开的playsinline的权限,好像在去年年末以前还须要向微信申请白名单才能够,如今已经不须要了。playsinline可让视频内嵌在h5页面中播放,这样会让用户感受这个视频就是h5的一部分,使用体验上会好不少。我使用的video代码以下:

<video class="video" id="video" x-webkit-airplay="allow" playsinline webkit-playsinline preload="auto" src="./video/rocket.mp4"></video>

在开始测试的时候发现,虽然视频能够内嵌播放了,可是在视频上会出现一个全屏和一个小窗的按钮。点击全屏按钮,视频会全屏播放,播放完还会显示广告。。。点击小窗按钮,视频会缩小成小窗。这两个按钮对于报告来讲,就是多此一举了。后面了解到这两个按钮是能够隐藏的,可是须要向浏览器x5内核那边申请白名单。申请后白名单后,按钮就不会出现了

andriod的机器不支持autoplay,必定须要有交互(touch,click等)来能播放,因此在第一页的时候当用户touchstart的时候,调用下video.play();video.pause().同时,iphone不支持preload,在第一页调用了video.play(),会触发视频的下载,在最后须要播放的时候,视频能够顺利的播放。

视频初始化在各个手机上表现的形式并不同,可是又须要有一个表现一致的效果。解决办法是,在尚未进入到最后一页的时候,设置video的宽高都为1px,等进入到最后一页的时候,在把宽度设为100%,高度设为auto。同时把视频的第一帧设为最后一页的背景图,这样每一个人看到的第一眼画面都是同样的。这里须要注意一点,在设置背景图的时候background-size应该设置为cover,否则在播放视频的时候,若是视频的宽高比跟手机宽高比不同会致使第一帧跳动的感受,体验上会打折扣。

在视频播放完后,会有文字再显示出来。 开始的作法是监听videoend 事件,可是这在iphone 上会出现屏幕黑一下,再出现文字。体验上又会打折扣了。问题引发的缘由,应该是视频播放完了,播放器的变成了黑色,就像在pc上播放完,播放器黑掉同样。解决的办法是: 设置一个定时器监听video的currentTime,当currentTime距离视频播放的时候还差几百毫秒的时候,显示文字,隐藏视频。大概的代码以下:

var videoTimer = setInterval(function () { if(video[0].currentTime > 6.5){ if(!videoEnd){ $(".check").show(); $(".pub").show(); $(".p2").css({'opacity': 1}); $(".check").addClass('check-ani'); $(".pub").addClass('check-ani'); $(".dong").addClass('bounceInDown'); $(".wish").addClass('wish-ani'); videoEnd = 1; } } }, 200);

不过这须要在制做视频的时候把这一段的时间留出来,同时也要考虑视频结束时跟文字出来之间的衔接,这能够跟设计师讨论研究了。

难题: 在iphone上偶尔会出现,视频不会播放。可是若是刷新下页面视频就能够正常的播放了。 在用测试机来重现这种状况的时候,又没有遇到,很差定位到具体是啥缘由。 如今只有一个猜想的缘由:由于 video的play()方法即便是调用了,可是也不必定保证会播放。猜想多是视频没有缓冲好,在调用play() 方法后,视频并无播放成功。 后面也是采起了定时去调用video的play()方法来尝试解决这个问题,如今热度也过了,也没有收到视频没有播放的反馈。若是各位客官有碰到视频没有播放的状况,麻烦留言通知声。 在监听视频有没有播放,是经过video 的timeupdate的事件来判断,timeupdate事件在iOS和Android上表现一致。具体的代码以下:

var videoPlayed = false; video.on("timeupdate", function () { videoPlayed = true; }); // 到第九页时判断 if(pageIndex === 9){ videoPlayed = false; videoPlayedTimer = setInterval(function () { if(!videoPlayed){ playVideo(); } }, 300); playVideo(); }

补充:
8.使用视频的时候,开始设计师导出的视频有1M多,这在移动端感受仍是有点太大了,何况视频只有7s。 后来使用了ffmpeg来压缩一下,视频大小减小了不少。从最终的1.8M 减小到了330kb。同时在各个手机上的视频清晰度变化肉眼是很难发现的。我使用的是ffmpeg默认的转换参数,固然你们也能够根据须要本身调整。

相关文章
相关标签/搜索