01 移動頁面開發(fā)
1.1頁面布局
1.1.1 viewport
viewport顽素,視圖窗口咽弦,指移動設備上能用來顯示頁面的那部分區(qū)域。
默認情況下戈抄,部分移動設備上的瀏覽器會把自己默認的viewport設為980像素甲锡,也可能是其他值茶袒。
1)設備像素
設備物理像素指設備顯示屏中使用的最小顯示單元食磕,也就是屏幕分辨率弦赖。iphone5是640*1136像素,iphone6是750*1334像素裸诽。
設備獨立像素指web編程中的邏輯像素嫂用,也就是css像素。iphone5的css像素是320*568像素丈冬。
2)像素密度(PPI)
PPI是用來表示設備每英寸所擁有的物理像素數(shù)目。這個數(shù)值越高埂蕊,我們看到的屏幕越清晰往弓。
iphone5的PPI大約等于326疏唾。
當顯示屏的PPI超過某一數(shù)值時函似,人的肉眼就無法分辨其中的單獨像素了撇寞,這就是Retina顯示屏牌废。
3)設備像素比DPR
DPR指物理像素和CSS像素的比例啤握。
var dpr = window.devicePixelRatio;
在前端鸟缕,CSS像素是常用的尺寸單位叁扫。對于常規(guī)顯示屏來說,物理像素和CSS像素的比值是1:1畜埋,但是在Retina屏幕設備中,一個CSS像素可能等于多個物理像素畴蒲。
關于設備像素悠鞍、像素密度及設備像素比等具體的數(shù)據(jù)可以到網(wǎng)站http://screensiz.es/上查看。
4)3個viewport
<1>Layout viewport
可以通過 document.documentElement.clientWidth,document.documentElement.clientHeight獲取
<2>Visual viewport
瀏覽器或者APP的webview中的可視區(qū)域模燥,稱為visual viewport咖祭,可以通過window.innerWidth和window.innerHeight獲取。
<3>Ideal viewport
Ideal viewport是一個理想中的蔫骂、抽象的視圖么翰,在這個視圖下,圖片和文字無論在什么設備和分辨率下辽旋,看起來都會保持差不多的大小浩嫌。
Ideal viewport的寬度并沒有一個固定的尺寸,不同的設備之間存在差異补胚。
通過設置viewport為width=device-width可以將layout viewport的寬度設置為Ideal viewport的寬度码耐。
5)設置viewport
為了將瀏覽器默認的layout viewport寬度設置為Ideal viewport的寬度,在開發(fā)移動頁面時一般都會在head標簽中輸入以下這段代碼溶其。
<meta name ="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0">
這段meta標簽的作用就是讓當前的layout viewport的寬度等于設備的Ideal viewport的寬度骚腥,同時不允許用戶手動縮放。
viewport可以用js動態(tài)的修改瓶逃。
6)圖片模糊問題
在Retina顯示屏等屏幕下束铭,一個位圖像素中對應了多個物理像素廓块,導致位圖像素中的色彩值不夠分,多出來的那些物理像素只能就近取色契沫,從而導致圖片模糊带猴。
解決方案就是將圖片原本的尺寸放大一定的倍數(shù),這個倍數(shù)便是參考DPR值埠褪,一般放大兩倍設計即可浓利,現(xiàn)在也有很多放大3倍。
1.1.2 布局形式
1)傳統(tǒng)頁面布局
一是需要考慮Retina屏幕的內(nèi)容清晰度钞速,主要內(nèi)容限定在640px像素以內(nèi)贷掖。
二是要注意測試不同分辨率的移動設備下,頁面兩邊的背景圖留白問題渴语。
前端重構時所有元素的尺寸都縮小1倍
2)滑屏頁面布局
通過CSS百分比來設置頁面高度實現(xiàn)每一屏100%撐滿
通過js實現(xiàn)滑屏效果苹威,通過記錄手指在屏幕上的位移量,計算滑動的方向驾凶,當手指離開屏幕時執(zhí)行滑動切換牙甫。
1.1.3 Media Queries
通過CSS3的媒體查詢來為不同設備應用不同的CSS規(guī)則。
1)使用Media queries
方式1:用link在<head>外鏈樣式表
<link rel="stylesheet" media="screen and (max-width:320px)" href="ip5.css"/>
方式2:直接寫入<head>的style里
@media screen and (max-width:320px){background:#fff;}
and用于鏈接多個媒體條件调违,當頁面是豎屏并且分辨率在320px以上這樣寫
screen and (min-width:320px) and (orientation:landscape)
css3準備了許多媒體條件
device-aspect-ratio:高寬比例
device-height:設備屏幕輸出高度
device-width:設備屏幕輸出寬度
height:窗口渲染的高度
width:窗口渲染的寬度
resolution:分辨率
orientation:橫/豎屏
grid:是否基于柵格設備
color-index:色彩表中的色彩數(shù)
color:每種色彩的字節(jié)數(shù)
css3新增的媒體類型
all:所有設備
braille:盲文觸覺反饋設備
embossed:盲文打印機
handled:手持設備
print:打印預覽
projection:投影設備
screen:彩色顯示器
speech:語音同步器
tty:打字機
tv:電視設備
2)媒體查詢中的斷點設置
斷點是指頁面布局發(fā)生改變的臨界點窟哺。
第1種:根據(jù)設備尺寸設置,有新尺寸設備需要額外適配
根據(jù)設備寬度設置(Ideal viewport的寬度尺寸)
@media screen and (max-width:320px){針對iphone5/5s的樣式設備}
@media screen and (max-width:360px){針對部分android的樣式設備}
@media screen and (max-width:375px){針對iphone6/6s的樣式設備}
@media screen and (max-width:414px){針對iphone6p/6sp的樣式設備}
@media screen and (max-width:768px)針對ipad mini豎屏的樣式設備{}
根據(jù)設備方向設置
@media screen and (orientation:portrait){針對豎屏時的樣式設備}
@media screen and (orientation:landscape){針對豎屏時的樣式設備}
根據(jù)設備像素比設置
@media screen and (device-pixel-ratio:2){針對設備像素比為2的樣式設備}
第2種:根據(jù)頁面內(nèi)容尺寸設置技肩,主要用在將PC頁面適配多終端的工作中
@media screen and (max-width:1000px){針對瀏覽器視窗小于1000px時的樣式設備}
@media screen and (max-width:700px){針對瀏覽器視窗小于700px時的樣式設備}
1.1.4 屏幕適應
1)百分比布局
百分比布局適合移動端頁面的設備尺寸碎片化情況且轨。
width的百分比值是以父元素的寬度為參考計算的
height在實際工作中只有在父元素的高度是一個指定值時,其子元素設置的百分比高度才會起作用虚婿,否則高度會被重置為auto旋奢。
W(元素當前百分比寬度)/H(padding-bottom) = 圖片真實寬度/圖片真實高度
2)縮放法
思路是,直接按640px重構設計稿然痊,通過計算瀏覽器的實際寬度和頁面寬度之間的比例至朗,對頁面進行縮放。
(function(fixwidth,id){
var elm = document.getElementById(id);
function setzoom(){
var cliwidth = document.documentElement.clientWidth || document.body.clientWidth;
var blwidth = cliwidth/fixwidth;
elm.style.zoom = blwidth;
};
window.addEventListener('resize',setzoom,false);
setzoom();
})(640,'wrap')
打開頁面和出行窗口大小改變時剧浸,運行setzoom函數(shù)锹引。setzoom函數(shù)先獲取屏幕分辨率,然后通過設計稿來計算縮放比例唆香。
好處是可以按設計稿的尺寸進行頁面開發(fā)粤蝎,然后讓頁面自動根據(jù)瀏覽器的分辨率進行縮放。
缺點是高度是隨著寬度進行等比縮放的袋马,所以滑屏布局不適合初澎。
3)Rem自適應
根據(jù)根頁面<html>標簽的字號匹配大小。比如<html>的字號font-size:20px,那么CSS設定1rem的頁面元素實際上會顯示20px的大小碑宴,1.2rem會顯示24px大小软啼。
Rem不僅可以作為字號尺寸單位,還可用于其他如width,height,margin,padding等延柠。
和縮放法的思路一樣祸挪,如果整個頁面的容器元素尺寸都是以rem為單位,只需根據(jù)當前瀏覽器分辨率動態(tài)的設置根目錄的字號尺寸贞间,頁面就可以自動地去適應分辨率了贿条。
將<html>標簽的字號設置成font-size:100px,比較方便處理增热。
(function(){
if(!window.addEventListener) return;
var html = document.documentElement;
function setfont(){
var cliwidth = html.clientWidth;
html.style.fontSize = 100*(cliwidth/640)+'px';
}
document.addEventListener('DOMContentLoaded',setfont,false)
})()
setfont函數(shù)先獲取屏幕分辨率整以,然后按比例設置頁面<html>標簽的字號。
對于雪碧圖背景峻仇,設置好相應的background-size和background-position就可以了公黑。
rem適用于移動端,PC部分瀏覽器不支持摄咆。
4)模塊和內(nèi)容的適應
針對PC和移動的特點凡蚜,在模塊和內(nèi)容的顯示上做一些小的調(diào)整和刪減。
可以使用媒體查詢針對大小手機分辨率做一些調(diào)整吭从。
1.1.5 內(nèi)容排布技巧
1)視頻與iframe的自適應
w(元素當前百分比寬度)/H(padding-bottom)=4/3or16/9or16/10
.video{position:relative;width:100%;height:0;pading:0 0 56.25% 0;/*按照16:9的比例計算獲得*/}
.video video{position:absolute;top:0;left:0;width:100%;height:100%;}
<div class="video">
<video src="video.mp4" controls="controls"></video>
</div>
2)水平垂直居中
可以使用display:box來實現(xiàn)在移動端的水平垂直居中朝蜘,加上前綴-webkit-和-moz-
外框的樣式
.wrap{
width:100%;
height:100%;
display:-webkit-box;
-webkit-box-orient:horizontal;/*設置子元素的排列方式*/
-webkit-box-pack:center;/*水平居中*/
-webkit-box-align:center;/*垂直居中*/
}
1.2 頁面調(diào)試
Chrome開發(fā)者工具
win操作系統(tǒng)下,f12鍵可以喚起開發(fā)者工具涩金。
1.3 常用庫和框架
1.3.1 jquery mobile 基于jquery和jquery UI
1.3.2 zepto 提供與jquery類似的API芹务,但并不是100%覆蓋jquery。
zepto支持自定義模塊打包鸭廷,可以按自己的業(yè)務需求進行打包下載。
1.3.3 cocos2d
cocos2d-JS是整合了cocos2d-html5和cocos2d-x javascript bindings的游戲引擎熔吗,一次編碼可游戲同時部署在網(wǎng)頁和原生應用渠道辆床。
1)目錄結構
frameworks--框架文件
res--圖片、plist及音頻文件
src--我們寫的js文件
tools--工具類文件
.cocos-project.json
CMakeLists.txt
index.html
main.js--游戲入口
project.json--項目配置文件
在index.html頁面加載了一個游戲畫布canvas和游戲入口桅狠,其中main.js文件如下:
cc.game.onStart = function(){
? cc.view.adjustViewPort(true);//設置瀏覽器meta來適配屏幕
? cc.view.setDesignResolutionSize(320,480,cc.ResolutionPolicy.SHOW_ALL);//分辨率設置
? cc.view.resizeWithBrowserSize(true);
? //先預加載資源
? cc.LoaderScene.preload(g_resources,function(){
? ? cc.director.runScene(new MainMenuScene());//導演啟動場景
? },this)
}
cc.game.run();
Project.json文件如下:
{
"project_type":"javascript",//工程類型
"debugMode":1,//debug模式
"showFPS":true,//是否顯示FPS
"frameRate":60,//幀率
"id":"gameCanvas",//canvas的id
"renderMode":0,//渲染模式
"engineDir":"frameworks/cocos2d-html5",//引擎路徑
"modules":["cocos2d"],
"jsList":[//自定義js源文件的一個集合
? "src/resource.js",
? "src/app.js",
]
}
src文件夾中的resource.js文件是用來填寫預加載的圖片列表讼载,如下:
var res = {
HelloWorld_png:"res/HelloWorld.png",
CloseNormal_png:"res/CloseNormal.png",
CloseSelected_png:"res/CloseSelected.png",
}
var g_resources=[];
for(var i in res){
? g_resources.push(res[i])
}
src文件夾中的app.js,新建了一個層并在這個層當中添加了一張圖片中跌,最后把這個層添加到場景中咨堤,如下:
var HelloWorldLayer=cc.Layer.extend({
sprite:null,
ctor:function(){
? this._super();
? this.sprite=new cc.Sprite(res.HelloWorld_png);
? this.addChild(this.sprite)
}
})
var HelloWorldScene = cc.Scene.extend({
? onEnter:function(){
? ? this._super();
? ? var layer=new HelloWorldLayer();
? ? this.addChild(layer);
? }
})
2)Scene場景
Scene代表我們在游戲中需要構建不同的場景,如游戲菜單漩符、游戲界面及游戲設置等一喘。
var GameLayer = cc.Layer.extend({
? init:function(){
? //需要顯示的場景內(nèi)容,例如背景
? }
})
var GameScene = cc.Scene.extend({
? onEnter:function(){
? ? this._super();
? ? var layer = new GameLayer();
? ? this.addChild(layer);
? ? layer.init();
? }
})
場景跳轉到另一個場景
var scene = new GameScene();
cc.director.runScene(scene);
3)Sprite(精靈)
sprite是一個2D圖像,可以對它進行移動凸克,旋轉议蟆,縮放及動畫等操作。
顏色精靈
var colorSprite = new cc.Sprite();
colorSprite.setTextureRect(cc.rect(0,0,128,128));
colorSprite.setColor(cc.color(255,128,128));
this.addChild(colorSprite)
普通精靈
var sprite = new cc.Sprite(res.bg_png);
this.addChild(sprite);
var rectSprite = new cc.Sprite(res.bg_png,cc.rect(x,y,w,h));//剪切其中的一小塊
this.addChild(rectSprite)
使用texture創(chuàng)建
var texture = cc.textureCache.addImage("res/bg.png");
var? textureSprite= new cc.Sprite(texture);
this.addChild(textureSprite);
通過plist(幀動畫常用到)
cc.spriteFrameCache.addSpriteFrames(res.skill_plist);
var frameSprite =new cc.Sprite("#skill_1.png");
this.addChild(frameSprite);
4)定時器
schedule表示間隔執(zhí)行自定義函數(shù)萎战,scheduleOnce表示執(zhí)行一次自定義函數(shù)咐容。
schedule(callback_fn,interval,repeat,delay)
scheduleOnce(callback_fn,delay)
callback_fn調(diào)用的方法名
interval間隔多久進行調(diào)用
repeat重復的次數(shù)
delay延遲多久再進行調(diào)用
schedule(callback_fn)每幀都調(diào)用一次,調(diào)用無數(shù)次蚂维,馬上調(diào)用
schedule(callback_fn,interval)間隔interval調(diào)用一次戳粒,調(diào)用無數(shù)次,馬上調(diào)用
scheduleUpdate每隔一幀執(zhí)行一次默認函數(shù)update()
var Helloworld = cc.Layer.extend({
? init:function(){
? ? this._super();
? ? this.schedule(this.timeCallback,2,2,1)
? ? this.scheduleOnce(this.timeCallback,2)
? ? this.scheduleUpdate();
? ? return true;
? },
? timeCallback:function(dt){},
? update:function(dt){}
})
停止定時器
unschedule(callback_fn);停止指定的定時器
unscheduleAllCallbacks();停止所有的定時器
unscheduleUpdate();停止update方法
5)Action動作系統(tǒng)
cc.MoveTo();移動到這里
cc.MoveBy();相對于之前點再移動
cc.ScaleTo();
cc.scaleBy();
cc.RotateTo();
cc.RotateBy();
cc.JumpTo();
cc.JumpBy();
cc.FadeIn();
cc.FadeOut();
帶By的方法都是支持reverse()方法的虫啥,即獲取反向動作蔚约。
var move1 = new cc.MoveBy(2,cc.p(100,0));
var move2 = move1.reverse();
sp.runAction(new cc.Sequence(move1,move2));
順序執(zhí)行Sequence和并行執(zhí)行Spawn
6)音頻
播放(第 1個參數(shù)為音頻文件,第2個參數(shù)為是否循環(huán)播放)
cc.audioEngine.playMusic(res.bg_mp3,false);播放背景音頻
cc.audioEngine.playEffect(res.effect_mp3,false)播放動作音效音頻
暫停
cc.audioEngine.pauseMusic();
cc.audioEngine.pauseEffect(soundId);
停止
cc.audioEngine.stopMusic();
cc.audioEngine.stopEffect(soundId);
cc.audioEngine.stopAllEffects();
恢復播放
cc.audioEngine.resumeMusic();
cc.audioEngine.resumeEffect(soundId);
cc.audioEngine.resumeAllEffects();
重新播放
cc.audioEngine.rewindMusic();
音量加減
cc.audioEngine.setMusicVolume(audioEngine.getMusicVolume()+0.1);
cc.audioEngine.setMusicVolume(audioEngine.getMusicVolume()-0.1);
cc.audioEngine.setEffectsVolume(audioEngine.getEffectsVolume()+0.1)
cc.audioEngine.setEffectsVolume(audioEngine.getEffectsVolume()-0.1)
判斷背景音樂是否在播放
if(cc.audioEngine.isMusicPlaying()){
? cc.log("playing")
}else{
? cc.log("not playing")
}
7)事件
觸摸事件
var listener = cc.EventListener.create({
? event:cc.EventListener.TOUCH_ONE_BY_ONE,//單次觸摸事件
? swallowTouches:true,//阻止事件傳遞給下一層
? onTouchBegan:function(touch,event){
? ? var target = event.getCurrentTarget();//獲取當前觸發(fā)事件的對象
? ? var locationInNode = target.convertToNodeSpace(touch.getLocation());//基于本地坐標獲取點擊坐標
? ? var size = target.getContentSize();//獲取當前節(jié)點大小
? ? var rect = cc.rect(0,0,size.width,size.height);//區(qū)域設定
? ? if(!(cc.rectContainsPoint(rect,locationInNode))){//判斷觸摸點是否在節(jié)點區(qū)域內(nèi)
? ? ? return false;
? ? }
? ? //開始邏輯處理
? ? cc.log("sprite began..x="+locationInNode.x+",y="+locationInNode.y);
? ? target.opacity = 180;
? ? return true;
? },
? onTouchMoved:function(touch,event){
? ? var target = event.getCurrentTarget();
? ? var delta = touch.getDelta();//返回從前一個觸摸點到當前點的距離delta
? ? target.x += delta.x;
? ? target.y += delta.y;
? },
? onTouchEnded:function(touch,event){
? ? var target = event.getCurrentTarget();
? ? target.opacity = 255;
? },
? onTouchCancelled:function(touch,event){
? ? cc.log("onTouchCancelled")
? }
})
重力感應事件
var Acceleration = TouchBaseLayer.extend({
? onEnter:function(){
? ? this._super();
? ? var sprite = new cc.Sprite(res.skill_png);
? ? this.addChild(sprite);
? ? sprite.setPosition(size.width/2,size.height/2);
? ? if('accelerometer' in cc.sys.capabilities){
? ? ? cc.inputManager.setAccelerometerEnabled(true);//開始重力加速度
? ? ? cc.inputManager.setAccelerometerInterval(1/60);//設置迭代間隔
? ? ? var listener =? cc.EventListener.create({
? ? ? ? event:cc.EventListener.ACCELERATION,
? ? ? ? callback:this.onListenerAccelerometer
? ? ? })
? ? ? cc.eventManager.addListener(listener,sprite)
? ? }else{
? ? ? cc.log("accelerometer not supported")
? ? }
? }孝鹊,
? onListenerAccelerometer:function(acc,event){
? ? var target = event.getCurrentTarget();
? ? var ballSize = target.getContentSize();
? ? var currPos = target.getPosition();
? ? var speed = 15;
? ? target.x = Acceleration.fixPos(currPos.x+acc.x*speed,ballSize.width/2,GC.w-ballSize.width/2);
? ? target.y = Acceleration.fixPos(currPos.y+acc.y*speed,ballSize.height/2,GC.h-ballSize.height/2);
? },
? onExit:function(){
? ? cc.inputManager.setAccelerometerEnabled(false);//關閉重力加速度監(jiān)聽
? ? this._super();
? },
? getEnTitle:function(){
? ? return "6.accelerometer";
? },
? getZhTitle:function(){
? ? return "重力加速計";
? }
})
1.3.4 CreateJS
CreateJS是一款基于Canvas的開發(fā)引擎炊琉,極大地簡化和降低了HTML5 Canvas項目的開發(fā)難度和成本。
CreateJS主要提供5類開發(fā)引擎又活,分別是EaselJS(負責圖形苔咪、事件、觸控及濾鏡等功能)柳骄、TweenJS(補間動畫)团赏、SoundJS(音頻控制)、PreloadJS(文件加載)及Zoe(生成圖片精靈及動畫數(shù)據(jù))耐薯。