前端基础入门——综合实战案例

352 阅读9分钟

PS切图

前端开发的大部分时间里都需要做网页重构,即把设计师提供的设计稿还原成网页代码,还原代码的过程就是切图+码代码

切图不仅是一门技术活,还是一门手艺活,要力求实用和低功耗

切图的准备工作

工具介绍

Photoshop

版本选择

PhotoshopCS4

缓存路径更改

最好不要存在C盘,使用久了会使系统内存负重太大

编辑-菜单-首选项-性能,将暂存盘改为除了C盘之外的其他盘

默认单位修改

网页中元素使用的默认单位是px,用Photoshop切图最好单位也设置为px

编辑-菜单-首选项-单位与标尺,将标尺和文字的单位都修改为像素

Photoshop预设

视图-标尺,窗口-段落/图层/信息/工具

常用工具

启用选择工具时,左上角的自动选择工具可以选择对图层进行操作,也可以对一组图层进行操作,图层中一个文件夹代表一个组

启用裁剪工具时,信息中显示选取的宽度和高度

启用字体工具并将光标点击至效果图中有文字的地方,字符信息中显示字体和字体颜色、大小、行高等信息

放大缩小图层:Alt+滚轮

撤销操作:Ctrl+Alt+Z

合并图层:Ctrl+E

图层面板的使用

点击图层面板中,不需要显示的图层左边的眼睛,可以隐藏这些图层

要使图层覆盖在另一个图层上面,可以交换图层面板中图层排列的顺序

借助辅助线辅助切图

网页设计师设计网页时往往有个视野宽度在0~1200px之间,并且是居中的,视野区外往往是一些不重要的内容

如何借助辅助线辅助切图?

启用移动工具拉取辅助线到合适的位置,再用裁剪工具,这时候裁剪区就会自动吸附到辅助线上

如何裁剪出背景为透明的可供使用的logo图?

新建一个透明图层,将裁剪出来的logo图拖拽到该透明图层上,点击图像-裁切,基于-透明像素,就能把没有颜色的区域都裁减掉

制作一个背景为透明的包含多图层的图片时,可以先合并图层再进行拖拽,也可以直接用裁剪工具裁剪下来,再进行拖拽

存储的格式

  • jpeg可以设置图片品质,但不能处理背景图片为透明的图片
  • png24不能被IE低版本浏览器所支持,图片会模糊,背景会被填充颜色,但png24可以利用js手段使得它在IE浏览器上也能正常显示出来
  • png8饱和度不如png24
  • wbmp是位图格式,不经常使用

裁切详解 

切片工具可以一次性裁剪多个图片并一键生成,裁切完成后,点击文件-存储为Web所用格式,存储。它会自动生成一个images的文件夹,里面是我们刚刚裁切的图片,但是它的效率很低,因为实际开发中往往不需要切那么多图,用css样式就可以实现同样的效果。

字体设置

如果我们电脑中没有设计稿上应用的字体,可以将这个字体下载下来,打开控制面板-字体,将字体文件拖拽进去,就成功在我们电脑上安装好新的字体,这时只需重启Photoshop就可以使用这个字体了。

总结

切图的优化

3秒定律

如果用户加载一个网页超过3秒,那么他就会关闭这个网页,导致我们丢失流量。

由于图片也要耗费资源,因此网页开发中图片越少越好。

利用样式平铺效果颜色代替图片

一些图片如果是自身的平铺图,就只需将宽度设置为1px并存储,在css中引用时设置实际宽度来进行平铺即可。

能够用css样式实现的效果,就不用图片来显示。

雪碧图的制作

使用“雪碧图”能够减少资源的耗费,将要使用的多个图片集中在一个背景为透明的png上,再用定位手段来显示我们想要的区域,这样一来,图片资源就只需加载一次。

字体图标的使用

以文字的形式代替图片的使用,现在很多图标库可以实现很多图片,就可以代替图片的使用。

快捷键的使用

实际开发过程中,敏捷开发才是第一生产力,要学会使用快捷键,这样可以加快开发速度,提高开发效率。

操作类快捷键

删除图层:delete

合并图层:Ctrl+E

工具类快捷键

移动:V

裁切:C

快捷键失效

可能是一些快捷键被输入法软件和QQ程序占用

切图辅助工具

Markman

可以帮助我们快速测量图中的颜色、字体代销、字体和文字之间的间距

TinyPNG

用于压缩png图片的大小

前端自动化

与中高级前端有关,可以快速生成雪碧图

宣传页项目

前端开发流程

产品经理做需求分析→视觉交互做视觉设计、交互动画设计→前端开发做前端静态页开发、动画效果开发

相关工具

编辑器:subline3

标注工具:pxcook

切图工具:Photoshop

开发前的准备工作

视觉设计稿PSD

设计图标注

PS切图

雪碧图(alloyteam.github.io/gopng/

页面内容和样式

开发技巧

从大到小

BEM开发模式

BEM代表块(Block),元素(Element),修饰符(Modifier)

模块(没有前缀,多个单词用 - 连接)

元素(元素在模块之后,可以有多个层级,以__连接)

修饰(某元素、或者某模块特别的状态,必须有一个状态名和状态值,使用 _ 连接)【比如某个标签的高亮状态】

居中法小结

文字垂直居中

将文字行高设置为与容器的高度一致

.item{
    height:38px;
    line-height:38px;
}

块元素垂直居中于父元素

给父元素设置为相对定位,子元素设置为绝对定位,距离顶部top50%的高度,margin-top为负的元素高度的一半

.father{
    position:relative;
}
.child{
    position:absolute;
    height:38px;
    top:50%;
    margin-top:-19px;
}

块元素水平居中

.item{
    width:38px;
    margin:0 auto;
}

网页动态效果

CSS动画背景知识

  1. 新的选择器,如:div:last-child(div节点下面的最后一个直接子节点)

  2. 多列布局,如:-webkit-column-count:3(就不必再用float)

  3. 圆角:bordder-radius

  4. 渐变背景图:background-image:-webkit-gradient(liner,0% 0%,100% 0%,from(#2A8BBE),to(#FE280E));

  5. transfrom

  6. transitions

  7. animation

CSS实现动画的两种方式

  1. transition:all 1s;(选择器中所有元素都在1s内完成变化)
  2. -webkit-animation:rock 2s infinite ease-in-out .5s;

动画效果测试脚本工具 

用鼠标点击模拟页面模块切换

用添加、移除class名的方法在给元素设置动画始末状态的样式

测试脚本小结

两种遍历,遍历对象{ },遍历数组[ ]

获取元素querySelector(一个元素)

字符串截取substr、字符串替换replace

CSS动画小结

构建复杂动画

CSS伪类的使用及触发动画效果

网页交互效果

帧动画定义→帧动画使用

背景图覆盖模式

.bg{
    background-size:cover;
}

作业

要点

  • 载入页面时,导航栏自上而下飘至视口顶部

先用transform中的translate把导航栏的默认样式设置为距离顶部为负的导航栏本身的高度。载入页面时,给导航栏添加init样式, 仍用transform中的translate设置为与顶部的距离为0。用transition实现两个样式的过渡效果,并将导航栏的position设置为fixed,z-index在最高层。

<!-- 基本样式 -->
.header__wrap{
	width: 100%;
	height: 60px;
	position: fixed;    <!-- 固定在视口顶部 -->    
	margin: 0 auto;
	background:linear-gradient(rgba(0,0,0,.8),rgba(255,255,255,0));    <!-- 渐变效果 -->
	z-index: 999;
}
<!-- 动画效果 -->
<!-- 默认样式 -->
.header__wrap{
	transition: all 1s;
	transform: translate(0,-60px);    <!-- 用translate进行相对定位,使页面载入前默认在视口顶部以上,不可见 -->
}
<!-- init样式 -->
.header__wrap_animate_init{
	transform: translate(0,0);    <!-- 用translate进行相对定位,使页面载入时过渡至视口顶部 -->
}
<!-- done样式 -->
.header__wrap_animate_done{
	transform: translate(0,0);    <!-- 这句是为了不让元素样式在后来整体页面元素状态切换中受到影响 -->
}
<!-- 滚动滑动条时导航栏变色 -->
.header__wrap_status_black{
	background-color: rgba(0,0,0,.5);
}
  • 载入页面时,自动播放第一屏的动画

由于刚载入时,并不会发生滚动条滚动事件,也就不会去调用onscroll中第一屏的done函数,因此要使页面一加载完成就播放第一屏的动画,需要先将第一屏的元素事先设置成init状态,然后在js文件中调用第一屏的done函数。

//载入页面时将所有屏幕设置为init状态,除了screen-1
window.onload=function(){
	for(k in screenAnimateElements){
		if(k==='.screen-1') continue;	//第一屏不在这里初始化,而是在css中加上init样式,并通过setTimeout来切换成done
		setScreenAnimateInit(k);
	}
    //获取滚动条高度
	var top=document.body.scrollTop;
    //第一屏
	if(top>0&&top<1*640-150){
		playScreenAnimationDone('.screen-1');
		switchNavItemsAcitve(0);
		navTip.style.left=40+'px';
	}
    //...
	
}
//调用setTimeout函数,载入页面0.2s后将第一屏由init切换成done(init是在css文件中设置好了的)
setTimeout(function(){
	playScreenAnimationDone('.screen-1');
},200)

其实有一个更简单的方法,直接把第一屏播放的条件由top>0改成top>=0,就可以不需要再单独去调用第一屏的done函数,也不需要在初始化时在css中单独去给第一屏元素设置init,而是像其他屏一样在载入时就用init函数去初始化。

window.onload=function(){
	for(k in screenAnimateElements){
		if(k==='.screen-1') continue;	//第一屏不在这里初始化,而是在css中加上init样式,并通过setTimeout来切换成done
		setScreenAnimateInit(k);
	}
	var top=document.body.scrollTop;
    //top>=0就可以在页面刚载入时就将init切换成done
	if(top>=0&&top<1*640-150){
		playScreenAnimationDone('.screen-1');
		switchNavItemsAcitve(0);
		navTip.style.left=40+'px';
	}
	//...
}
  • 载入页面时,导航栏的active元素默认是第一个

在css文件中给第一个元素设置status_active样式(文字highlight),并且用将滑动门设置在第一个元素的位置。

不在css文件中设置也可以,只要top=0就会调用switchNavItemsActive(0)来设置也能达到同样的效果。

window.onload=function(){
	for(k in screenAnimateElements){
		if(k==='.screen-1') continue;	//第一屏不在这里初始化,而是在css中加上init样式,并通过setTimeout来切换成done
		setScreenAnimateInit(k);
	}
	var top=document.body.scrollTop;
	if(top>=0&&top<1*640-150){    //重点是这里的top=0
		playScreenAnimationDone('.screen-1');    
		switchNavItemsAcitve(0);    //文字highlight
		navTip.style.left=40+'px';    //滑动门滑至第一个元素的位置
	}
	//...
	
}
  • 进入不同的屏幕时,自动播放相应的动画
  • 进入不同的屏幕时,导航栏/大纲的active元素随之改变
/* 播放屏内的元素动画的函数 */
var playScreenAnimationDone=function(screenCls){
	//播放动画,改init为done
	var screen=document.querySelector(screenCls);	//获取当前屏对象
	var animateElements=screenAnimateElements[screenCls];	//需要设置动画的元素
	for (var i=0;i<animateElements.length;i++) {
		var element=document.querySelector(animateElements[i]);	//遍历当前屏的所有元素
		var baseCls=element.getAttribute('class');	//先取出初始的class名(含init样式)
		element.setAttribute('class',baseCls.replace('_animate_init','_animate_done'));
        //把init样式替换成done样式
 	}
}
 
//获取导航栏元素
var navItems=getAllElem('.header__nav-item');
//获取大纲元素
var outlineItems=getAllElem('.outline__item');
 
//删除所有元素的active样式,再给当前元素设置active样式
var switchNavItemsAcitve=function(index){
	for(var i=0;i<navItems.length;i++){
		delCls(navItems[i],'header__nav-item_status_active');
		delCls(outlineItems[i],'outline__item_status_active');
	}
	addCls(navItems[index],'header__nav-item_status_active');
	addCls(outlineItems[index],'outline__item_status_active');
}
 
 
/* 在载入时调用样式init方法 */
window.onload=function(){
	for(k in screenAnimateElements){
		if(k==='.screen-1') continue;	
        //第一屏不在这里初始化,而是在css中加上init样式,并通过setTimeout来切换成done
		setScreenAnimateInit(k);
	}
	var top=document.body.scrollTop;
    //根据滚动条高度来判断当前位于哪个屏幕,并调用相应的done函数和switchNavItemsActive函数,改变滑动门位置
	if(top>=0&&top<1*640-150){
		playScreenAnimationDone('.screen-1');
		switchNavItemsAcitve(0);
		navTip.style.left=40+'px';
	}
	else if(top>=1*640-150&&top<2*640-150){
		playScreenAnimationDone('.screen-2');
		switchNavItemsAcitve(1);
		navTip.style.left=(40+1*101)+'px';
	}
	else if(top>=2*640-150&&top<3*640-150){
		playScreenAnimationDone('.screen-3');
		switchNavItemsAcitve(2);
		navTip.style.left=(40+2*101)+'px';
	}
	else if(top>=3*640-150&&top<4*640-150){
		playScreenAnimationDone('.screen-4');
		switchNavItemsAcitve(3);
		navTip.style.left=(40+3*101)+'px';
	}
	else{
		playScreenAnimationDone('.screen-5');
		switchNavItemsAcitve(4);
		navTip.style.left=(40+4*101)+'px';
	}
	
}
  • 点击导航标签或大纲标签时,定位至对应的屏幕
var setJump=function(i,lib){
	var item=lib[i];
	item.onclick=function(){
		document.body.scrollTop=i*640;    //滚动条高度的写入
	}
}
 
for(var i=0;i<navItems.length;i++){
	setJump(i,navItems);
}
for(var i=0;i<outlineItems.length;i++){
	setJump(i,outlineItems);
}
  • 鼠标移向导航中的某个元素时,滑动门滑至该元素,鼠标移走时,滑动门滑回当前屏对应的导航元素
//获取滑动门元素
var navTip=getElem('.header__nav-tip');
//初始位置有偏移,先进行调整
navTip.style.left=40+'px';
var setTip=function(index,lib){
	lib[index].onmouseover=function(){
        //鼠标滑入,定位至相应的导航标签
        navTip.style.left=(40+index*101)+'px';
	}
    //鼠标移出,找到当前页面对应的导航标签,将滑动门移至该标签下
	var activeIndex=0;
	lib[index].onmouseout=function(){
		for(var i=0;i<lib.length;i++){
            /* 找到当前选中的元素,是被激活的元素 */
            if(getCls(lib[i]).indexOf('header__nav-item_status_active')>-1)	
            {
                activeIndex=i;
                break;
            }
		navTip.style.left=(40+activeIndex*101)+'px';
	}
}
//给每个导航元素添加滑动事件
for(var i=0;i<navItems.length;i++){
	setTip(i,navItems);
}

总结

滑动门的位置是用navTip.style.left来控制的,它与active的不同之处在于:鼠标滑入时会跟着鼠标走,即获取当前鼠标移入的导航标签(传入函数的index),修改navTip.style.left,使滑动门滑动到鼠标所指的位置,当鼠标移出又回到当前屏对应的导航标签(遍历导航标签,找到当前设置了active样式的元素,记下其索引值,并修改navTip.style.left),由于这些操作都是对navTip.style.left进行修改,所以每次滑动门只会在一个位置,不会出现多个滑动门。而active只根据scrollTop来确定当前屏幕。

待改进

希望通过滚动条、导航、大纲进入某个屏幕时,都能重新播放动画,而不是只能有一次init→done,过后就不再生效

改进思路

滚动条每到一个屏幕区域时,就将其他屏幕再次设置为init状态,只有当滚动条再次移动到这些屏幕区域时,才将init状态改为done状态。个人觉得这样做有点麻烦,但是目前没有想到更好的方法。

成品图