如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里
變量包括:全局變量,局部變量
在JAvaScript中,函數中定義的變量是局部變量
分為:局部作用域和全局作用域
js中沒有塊級作用域---一對括號中定義的變量,這個變量可以在大括號外面使用
-
var num=10; //作用域鏈 級別:0
-
var num2=20;
-
var str = "abc"
-
function f1() {
-
var num2=20;
-
function f2() {
-
var num3=30;
-
console.log(num);
-
}
-
f2();
-
}
-
f1();
層層搜索,搜索到0級作用域的時候,如果還是沒有找到這個變量,結果就是報錯
(1)變量的提升
下面這種情況,變量的聲明被提前了,但是num的值并沒有提前,結果為undefined
-
//變量的提升
-
console.log(num);
-
var num=100;
-
-
-
//提升之后為:
-
var num;//變量的聲明提前
-
console.log(num);
-
var num=100;
(2)
函數聲明被提前,代碼仍然可以執行
-
//函數的聲明被提前了
-
f1();
-
function f1() {
-
console.log("這個函數,執行了");
-
}
但是對于下面這種情況,代碼報錯
-
f2();
-
var f2=function () {
-
console.log("小楊好帥哦");
-
}
-
-
//聲明提前后:
-
var f2;//為一個變量,undefind
-
f2();//undefind加括號是不被認可的,所以報錯
-
var f2=function () {
-
console.log("小楊好帥哦");
-
}
要想不報錯,代碼可以改為:
-
var f2;
-
f2=function () {
-
console.log("小楊好帥哦");
-
};
-
f2();
藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務。
如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里
form表單提交,之前有個下載的項目接口,需要上url上邊傳超級多東西,但是 url是限制長度的 每個瀏覽器限制的url長度還不一樣,所以就想到用form表單的action提交表單。
form標簽 定義和用法 詳細了解請點擊
標簽用于為用戶輸入創建 HTML 表單。
表單能夠包含 input 元素,比如文本字段、復選框、單選框、提交按鈕等等。
表單還可以包含 menus、textarea、fieldset、legend 和 label 元素。
表單用于向服務器傳輸數據。(我們要用到的)
在這里我就寫個用js調用事件提交表單。表單不在頁面上顯示的例子。
下面這段代碼 form標簽的屬性 method 就是請求方法 跟 jquery的ajax一樣這里我使用post請求、 form標簽的屬性 enctype 規定發送表單數據之前如何對其進行編碼、form標簽的屬性 target=”_blank” 就相當于在新頁面打開 我這里做的是下載 所以要在新頁面打開。
<form method="post" enctype="application/x-www-form-urlencoded" id="form-submit" target="_blank">
<input type="hidden" name="account" value="多毛大叔愛蘿莉"/>
<input type="hidden" name="password" value="7758521"/>
</form>
<button type="button" id="go">go</button> //這里的name就是相當于post屬性的參數 value就是你傳的值 type是hidden 是因為我不想再頁面上看到他所以讓他隱藏了
接下來我們用js調用事件 動態給 form 添加 action 屬性讓form知道我們要讓他請求拿個位置。
// js 獲取form表單 var form_submit = document.getElementById('form-submit'); // js獲取按鈕 var go = document.getElementById('go'); // 當點擊go時執行事件 go.addEventListener('click',function(){ // 動態給form表單設置請求位置 form_submit.active = "http://www.daxuehua.cn"; // 讓form表單提交 form_submit.submit()
})
藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務。如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里
四種touch事件
touchstart: //手指放到屏幕上時觸發
touchmove: //手指在屏幕上滑動式觸發
touchend: //手指離開屏幕時觸發
touchcancel: //系統取消touch事件的時候觸發
每個觸摸事件被觸發后,會生成一個event對象,event對象里額外包括以下三個觸摸列表
touches: //當前屏幕上所有手指的列表
targetTouches: //當前dom元素上手指的列表,盡量使用這個代替touches
changedTouches: //涉及當前事件的手指的列表,盡量使用這個代替touches
這些列表里的每次觸摸由touch對象組成,touch對象里包含著觸摸信息,主要屬性如下:
clientX / clientY: //觸摸點相對瀏覽器窗口的位置
pageX / pageY: //觸摸點相對于頁面的位置
screenX / screenY: //觸摸點相對于屏幕的位置
identifier: //touch對象的ID
target: //當前的DOM元素
注意:
手指在滑動整個屏幕時,會影響瀏覽器的行為,比如滾動和縮放。所以在調用touch事件時,要注意禁止縮放和滾動。
1.禁止縮放
通過meta元標簽來設置。
<meta name="viewport" content="target-densitydpi=320,width=640,user-scalable=no">
2.禁止滾動
preventDefault是阻止默認行為,在touchMove事件中使用可阻止默認行為滾動。
event.preventDefault();
3.解決穿透
在touchStart事件后添加touchMove事件的監聽,在touchMove事件里添加touchEnd事件的監聽,在touchEnd事件中移除touchMove和touchEnd的事件監聽,即可解決穿透問題
4.removeEventListener
傳入的處理事件函數一定是相同的函數,不能是匿名函數
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" Content="text/html; charset=utf-8;"> <title>移動端觸摸滑動</title> <meta name="author" content="rainna" /> <meta name="keywords" content="rainna's js lib" /> <meta name="description" content="移動端觸摸滑動" /> <meta name="viewport" content="target-densitydpi=320,width=640,user-scalable=no"> <style> *{margin:0;padding:0;} li{list-style:none;} .m-slider{width:600px;margin:50px 20px;overflow:hidden;} .m-slider .cnt{position:relative;left:0;width:3000px;} .m-slider .cnt li{float:left;width:600px;} .m-slider .cnt img{display:block;width:100%;height:450px;} .m-slider .cnt p{margin:20px 0;} .m-slider .icons{text-align:center;color:#000;} .m-slider .icons span{margin:0 5px;} .m-slider .icons .curr{color:red;} .f-anim{-webkit-transition:left .2s linear;} </style> </head> <body> <div class="m-slider"> <ul class="cnt" id="slider"> <li> <img src="http://imglf1.ph.126.net/qKodH3sZoVbPalKFtHS9mw==/6608946691259322175.jpg"> <p>20140813鏡面的世界,終究只是倒影??吹玫侥愕纳碛?,卻觸摸不到你的未來</p> </li> <li> <img src="http://imglf1.ph.126.net/40-jqH_j6EoCWnZOixY2pA==/4798022453110310215.jpg"> <p>20140812錫林浩特前往東烏旗S101必經之處,一條極美的鐵路。鐵路下面是個小型的鹽沼,淡淡的有了一絲天空之境的感覺??上г诖送媪艘粋€小時也沒有看見一列火車經過,只好繼續趕往東烏旗。</p> </li> <li> <img src="http://imglf0.ph.126.net/Jnmi2y51zVdjKAYlibtpFw==/3068640196117481166.jpg"> <p>20140811水的顏色為什么那么藍,我也納悶,反正自然飽和度和對比度拉完就是這個顏色的</p> </li> <li> <img src="http://imglf1.ph.126.net/79GPsjhwiIj8e-0nP5MsEQ==/6619295294699949331.jpg"> <p>海洋星球3重慶天氣熱得我想臥軌自殺</p> </li> <li> <img src="http://imglf1.ph.126.net/40-jqH_j6EoCWnZOixY2pA==/4798022453110310215.jpg"> <p>以上這些作品分別來自兩位設計師作為觀者,您能否通過設計風格進行區分</p> </li> </ul> <div class="icons" id="icons"> <span class="curr">1</span> <span>2</span> <span>3</span> <span>4</span> <span>5</span> </div> </div> <script> var slider = { //判斷設備是否支持touch事件 touch:('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch,
slider:document.getElementById('slider'), //事件 events:{
index:0, //顯示元素的索引 slider:this.slider, //this為slider對象 icons:document.getElementById('icons'),
icon:this.icons.getElementsByTagName('span'),
handleEvent:function(event){ var self = this; //this指events對象 if(event.type == 'touchstart'){
self.start(event);
}else if(event.type == 'touchmove'){
self.move(event);
}else if(event.type == 'touchend'){
self.end(event);
}
}, //滑動開始 start:function(event){ var touch = event.targetTouches[0]; //touches數組對象獲得屏幕上所有的touch,取第一個touch startPos = {x:touch.pageX,y:touch.pageY,time:+new Date}; //取第一個touch的坐標值 isScrolling = 0; //這個參數判斷是垂直滾動還是水平滾動 this.slider.addEventListener('touchmove',this,false); this.slider.addEventListener('touchend',this,false);
}, //移動 move:function(event){ //當屏幕有多個touch或者頁面被縮放過,就不執行move操作 if(event.targetTouches.length > 1 || event.scale && event.scale !== 1) return; var touch = event.targetTouches[0];
endPos = {x:touch.pageX - startPos.x,y:touch.pageY - startPos.y};
isScrolling = Math.abs(endPos.x) < Math.abs(endPos.y) ? 1:0; //isScrolling為1時,表示縱向滑動,0為橫向滑動 if(isScrolling === 0){
event.preventDefault(); //阻止觸摸事件的默認行為,即阻止滾屏 this.slider.className = 'cnt'; this.slider.style.left = -this.index*600 + endPos.x + 'px';
}
}, //滑動釋放 end:function(event){ var duration = +new Date - startPos.time; //滑動的持續時間 if(isScrolling === 0){ //當為水平滾動時 this.icon[this.index].className = ''; if(Number(duration) > 10){ //判斷是左移還是右移,當偏移量大于10時執行 if(endPos.x > 10){ if(this.index !== 0) this.index -= 1;
}else if(endPos.x < -10){ if(this.index !== this.icon.length-1) this.index += 1;
}
} this.icon[this.index].className = 'curr'; this.slider.className = 'cnt f-anim'; this.slider.style.left = -this.index*600 + 'px';
} //解綁事件 this.slider.removeEventListener('touchmove',this,false); this.slider.removeEventListener('touchend',this,false);
}
}, //初始化 init:function(){ var self = this; //this指slider對象 if(!!self.touch) self.slider.addEventListener('touchstart',self.events,false); //addEventListener第二個參數可以傳一個對象,會調用該對象的handleEvent屬性 }
};
slider.init(); </script> </body> </html>
藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務。如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里
寫在前面:
如果讓用簡單的幾句話說一下什么是原型,或者給原型下個定義,我覺得還是有點困難的,困難之處在于即使說了之后,對于聽的人來說,估計也是一頭霧水。不過,關于原型的一些基本的東西還是要說明的,這些基本的東西差不多就可以構成一個對原型的理解。首先,原型是函數才有的一個屬性;其次,原型就是一個對象,我們可以給它添加屬性或方法;最后,原型的作用是實現對象屬性的繼承。
每個對象都有一個隱藏的
每個函數都有一個
對象是沒有
通過原型
什么是原型鏈?
typeof在判斷引用數據類型時只能返回object和function,不能準確判斷引用數據類型時數組還是對象。而instanceof可以很好用于判斷引用數據類型。
用法:
instanceof是通過判斷對象
1、什么是對象?
對象就是屬性的集合;
2、對象與函數的關系?
對象都可以看做是由構造函數Object實例化生成的;
函數都可以看做是由構造函數Function實例化生成的;
構造函數Object也是由構造函數Function生成的;
1、原型prototype
__proto__
屬性,__proto__
屬性指向創建該對象的函數的原型prototype
;
prototype
屬性,其prototype
屬性值是一個對象;
prototype
屬性的,函數是沒有__proto__
屬性的;
prototype
,可以實現對象屬性的繼承,即創建在構造函數原型上的方法和屬性可以被所有由該構造函數生成的實例所共享;
2、原型鏈
原型鏈描述的是對象的繼承圖譜(類似于家譜圖),當訪問一個對象的屬性的時候,會在該對象中進行查詢,如果在該對象中沒有查詢到,則會沿著該對象的__proto__
線進行查詢,直到查詢到該屬性或者到Object.prototype,這樣層層向上查詢的線路就是該對象的原型鏈。
3、instanceof
A instanceof B
A
的原型鏈上是否存在B
的原型來確定A的數據類型;
如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
html, body {
margin: 0;
padding: 0;
height: 100%;
overflow: hidden;
}
.container {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div class="container">
<canvas id="cs"></canvas>
</div>
</body>
<script>
function MoveBalls(element, opts) {
var canvas = document.querySelector(element);
this.canvas = canvas;
this.ctx = canvas.getContext("2d");
var defaultOpts = {
total: 100,
color: "#00D0FF",
size: 1,
width: this.canvas.parentNode.clientWidth,
height: this.canvas.parentNode.clientHeight
};
var opts = opts || defaultOpts;
for (var key in opts) {
defaultOpts[key] = opts[key];
};
for (var key in defaultOpts) {
this[key] = defaultOpts[key];
};
opts = null;
defaultOpts = null;
// 鼠標坐標
this.coordinate = {
x: null,
y: null,
max: 100
};
// 粒子
this.dots = [];
// 含鼠標坐標的粒子數組
this.newDots = [];
// 總數
this.count = 0;
// requestAnimationFrame兼容處理
window.requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback) {
window.setTimeout(callback, 1000 / 60);
};
this.colorReg = /[rgba()]/g;
this.init();
};
MoveBalls.prototype = {
constructor: MoveBalls,
init: function () {
var _this = this;
this.freshResize();
this.mouseEvent();
this.getDots();
var timer = setTimeout(function () {
clearTimeout(timer);
_this.draw(_this)
}, 300);
},
colorCheck: function () {
this.canvas.style.color = this.color;
var colorData = this.canvas.style.color;
return colorData = colorData.replace(this.colorReg, "").split(",");
},
resize: function (self) {
var _this = self || this;
_this.canvas.width = _this.width;
_this.canvas.height = _this.height;
},
freshResize: function () {
this.resize();
var _this = this;
window.addEventListener("resize", function () {
_this.resize(_this);
});
},
mouseEvent: function () {
var _this = this;
_this.canvas.addEventListener("mousemove", function (e) {
var e = e || winodw.event;
_this.coordinate.x = e.offsetX ? e.offsetX : e.layerX;
_this.coordinate.y = e.offsetY ? e.offsetY : e.layerY;
});
_this.canvas.addEventListener("mouseout", function () {
_this.coordinate.x = null;
_this.coordinate.y = null;
})
},
getDots: function () {
while(this.count < this.total) {
var x = Math.random() * this.canvas.width;
var y = Math.random() * this.canvas.height;
var xMove = Math.random() * 2 - 1;
var yMove = Math.random() * 2 - 1;
this.dots.push({
x: x,
y: y,
xMove: xMove,
yMove: yMove,
max: 100
});
this.count ++;
}
},
draw: function (self) {
var _this = self || this;
var ctx = _this.ctx;
ctx.clearRect(0, 0, _this.canvas.width, _this.canvas.height);
_this.newDots = [_this.coordinate].concat(_this.dots);
_this.dots.forEach(function (dot) {
dot.xMove *= (dot.x > _this.canvas.width || dot.x < 0) ? -1 : 1;
dot.yMove *= (dot.y > _this.canvas.height || dot.y < 0) ? -1 : 1;
dot.x += dot.xMove;
dot.y += dot.yMove;
// 繪制點
ctx.save();
ctx.beginPath();
ctx.arc(dot.x, dot.y, _this.size, 0, Math.PI * 5);
ctx.fillStyle = _this.color;
ctx.fill();
ctx.restore();
// 循環比對粒子間的距離
for (var i = 0; i < _this.newDots.length; i ++) {
var newDot = _this.newDots[i];
// 如果是第一個點,則跳過
if(newDot === dot || newDot.x === null || newDot.y === null) continue;
var xDistance = dot.x - newDot.x;
var yDistance = dot.y - newDot.y;
var distance = Math.sqrt(Math.pow(xDistance, 2) + Math.pow(yDistance, 2));
// 顏色深度
var deep = 0;
// 小于最小距離,則連線
if (distance <= newDot.max) {
// 附近的小球向鼠標位置移動
if(newDot === _this.coordinate && distance > (newDot.max / 2)) {
dot.x -= xDistance * 0.05;
dot.y -= yDistance * 0.05;
}
// 距離越近---值越大---顏色越深
deep = (newDot.max - distance) / newDot.max;
// 畫線
ctx.save();
ctx.beginPath();
ctx.lineWidth = deep / 2;
var colorInfo = _this.colorCheck();
ctx.strokeStyle = "rgba(" + colorInfo[0] + ", " + colorInfo[1] + ", " + colorInfo[2] + "," + (deep + 0.4) + ")";
ctx.moveTo(dot.x, dot.y);
ctx.lineTo(newDot.x, newDot.y);
ctx.stroke();
ctx.restore();
}
}
// 將已經計算過的粒子刪除,減少遍歷的總數量
_this.newDots.splice(_this.newDots.indexOf(dot), 1);
});
window.requestAnimationFrame(function (obj) {
_this.draw(_this);
});
}
}
var moveBalls = new MoveBalls("#cs", {total: 66, color: "#00D0FF", size: 1});
</script>
</html>
藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務
如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里
字號
工作了有一段時間,基本上都在搞移動端的前端開發,工作的過程中遇到過很多問題,bug的解決方案,記錄下來,以便后用?。。热莶⒉皇呛苋?,以后每遇到一個問題都會總結在這里,分享給大家!
一、meta標簽相關知識
1、移動端頁面設置視口寬度等于設備寬度,并禁止縮放。
<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
2、移動端頁面設置視口寬度等于定寬(如640px
),并禁止縮放,常用于微信瀏覽器頁面。
<meta name="viewport" content="width=640,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
3、禁止將頁面中的數字識別為電話號碼
<meta name="format-detection" content="telephone=no" />
4、忽略Android平臺中對郵箱地址的識別
<meta name="format-detection" content="email=no" />
5、當網站添加到主屏幕快速啟動方式,可隱藏地址欄,僅針對ios的safari
-
<meta name="apple-mobile-web-app-capable" content="yes" />
-
<!-- ios7.0版本以后,safari上已看不到效果 -->
6、將網站添加到主屏幕快速啟動方式,僅針對ios的safari頂端狀態條的樣式
-
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
-
<!-- 可選default、black、black-translucent -->
viewport模板
-
<!DOCTYPE html>
-
<html>
-
<head>
-
<meta charset="utf-8">
-
<meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
-
<meta content="yes" name="apple-mobile-web-app-capable">
-
<meta content="black" name="apple-mobile-web-app-status-bar-style">
-
<meta content="telephone=no" name="format-detection">
-
<meta content="email=no" name="format-detection">
-
<title>title</title>
-
<link rel="stylesheet" href="index.css">
-
</head>
-
-
<body>
-
content...
-
</body>
-
-
</html>
二、CSS樣式技巧
1、禁止ios和android用戶選中文字
.css{-webkit-user-select:none}
2、禁止ios長按時觸發系統的菜單,禁止ios&android長按時下載圖片
.css{-webkit-touch-callout: none}
3、webkit去除表單元素的默認樣式
.css{-webkit-appearance:none;}
4、修改webkit表單輸入框placeholder的樣式
-
input::-webkit-input-placeholder{color:#AAAAAA;}
-
input:focus::-webkit-input-placeholder{color:#EEEEEE;}
5、去除android a/button/input
標簽被點擊時產生的邊框 & 去除ios a
標簽被點擊時產生的半透明灰色背景
a,button,input{-webkit-tap-highlight-color:rgba(255,0,0,0);}
6、ios使用-webkit-text-size-adjust
禁止調整字體大小
body{-webkit-text-size-adjust: 100%!important;}
7、android 上去掉語音輸入按鈕
input::-webkit-input-speech-button {display: none}
8、移動端定義字體,移動端沒有微軟雅黑字體
-
/* 移動端定義字體的代碼 */
-
body{font-family:Helvetica;}
三、其他技巧
1、手機拍照和上傳圖片
-
<!-- 選擇照片 -->
-
<input type=file accept="image/*">
-
<!-- 選擇視頻 -->
-
<input type=file accept="video/*">
2、取消input在ios下,輸入的時候英文首字母的默認大寫
<input autocapitalize="off" autocorrect="off" />
3、打電話和發短信
-
<a href="tel:0755-10086">打電話給:0755-10086</a>
-
<a href="sms:10086">發短信給: 10086</a>
四、CSS reset
-
/* hcysun */
-
@charset "utf-8";
-
/* reset */
-
html{
-
-webkit-text-size-adjust:none;
-
-webkit-user-select:none;
-
-webkit-touch-callout: none
-
font-family: Helvetica;
-
}
-
body{font-size:12px;}
-
body,h1,h2,h3,h4,h5,h6,p,dl,dd,ul,ol,pre,form,input,textarea,th,td,select{margin:0; padding:0; font-weight: normal;text-indent: 0;}
-
a,button,input,textarea,select{ background: none; -webkit-tap-highlight-color:rgba(255,0,0,0); outline:none; -webkit-appearance:none;}
-
em{font-style:normal}
-
li{list-style:none}
-
a{text-decoration:none;}
-
img{border:none; vertical-align:top;}
-
table{border-collapse:collapse;}
-
textarea{ resize:none; overflow:auto;}
-
/* end reset */
五、常用公用CSS style
-
/* public */
-
-
/* 清除浮動 */
-
.clear { zoom:1; }
-
.clear:after { content:''; display:block; clear:both; }
-
-
/* 定義盒模型為怪異和模型(寬高不受邊框影響) */
-
.boxSiz{
-
-webkit-box-sizing: border-box;
-
-moz-box-sizing: border-box;
-
-ms-box-sizing: border-box;
-
-o-box-sizing: border-box;
-
box-sizing: border-box;
-
}
-
-
/* 強制換行 */
-
.toWrap{
-
word-break: break-all; /* 只對英文起作用,以字母作為換行依據。 */
-
word-wrap: break-word; /* 只對英文起作用,以單詞作為換行依據。*/
-
white-space: pre-wrap; /* 只對中文起作用,強制換行。*/
-
}
-
-
/* 禁止換行 */
-
.noWrap{
-
white-space:nowrap;
-
}
-
-
/* 禁止換行,超出省略號 */
-
.noWrapEllipsis{
-
white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
-
}
-
-
/* 文字兩端對齊 */
-
.text-justify{
-
text-align:justify;
-
text-justify:inter-ideograph;
-
}
-
-
/* 定義盒模型為 flex布局兼容寫法并讓內容水平垂直居中 */
-
.flex-center{
-
display: -webkit-box;
-
display: -moz-box;
-
display: -ms-flexbox;
-
display: -o-box;
-
display: box;
-
-
-webkit-box-pack: center;
-
-moz-box-pack: center;
-
-ms-flex-pack: center;
-
-o-box-pack: center;
-
box-pack: center;
-
-
-webkit-box-align: center;
-
-moz-box-align: center;
-
-ms-flex-align: center;
-
-o-box-align: center;
-
box-align: center;
-
}
-
-
/* public end */
六、flex布局
1、定義彈性盒模型兼容寫法
-
/*
-
box
-
inline-box
-
*/
-
display: -webkit-box;
-
display: -moz-box;
-
display: -ms-flexbox;
-
display: -o-box;
-
display: box;
2、box-orient 定義盒模型內伸縮項目的布局方向
-
/**
-
* vertical column 垂直
-
* horizontal row 水平 默認值
-
*/
-
-webkit-box-orient: horizontal;
-
-moz-box-orient: horizontal;
-
-ms-flex-direction: row;
-
-o-box-orient: horizontal;
-
box-orient: horizontal;
3、box-direction 定義盒模型內伸縮項目的正序(normal默認值)、倒敘(reverse)
-
/* Firefox */
-
display:-moz-box;
-
-moz-box-direction:reverse;
-
/* Safari、Opera 以及 Chrome */
-
display:-webkit-box;
-
-webkit-box-direction:reverse;
4、box-pack 對盒子水平富??臻g的管理
-
/*
-
start
-
end
-
center
-
justify
-
*/
-
-webkit-box-pack: center;
-
-moz-box-pack: center;
-
-ms-flex-pack: center;
-
-o-box-pack: center;
-
box-pack: center;
5、box-pack 對盒子垂直方向富??臻g的管理
-
/*
-
start
-
end
-
center
-
*/
-
/* box-align */
-
-webkit-box-align: center;
-
-moz-box-align: center;
-
-ms-flex-align: center;
-
-o-box-align: center;
-
box-align: center;
6、定義伸縮項目的具體位置
-
/*-moz-box-ordinal-group:1;*/ /* Firefox */
-
/*-webkit-box-ordinal-group:1;*/ /* Safari 和 Chrome */
-
.box div:nth-of-type(1){-webkit-box-ordinal-group:1;}
-
.box div:nth-of-type(2){-webkit-box-ordinal-group:2;}
-
.box div:nth-of-type(3){-webkit-box-ordinal-group:3;}
-
.box div:nth-of-type(4){-webkit-box-ordinal-group:4;}
-
.box div:nth-of-type(5){-webkit-box-ordinal-group:5;}
7、定義伸縮項目占空間的份數
-
-moz-box-flex:2.0; /* Firefox */
-
-webkit-box-flex:2.0; /* Safari 和 Chrome */
-
-
.box div:nth-of-type(1){-webkit-box-flex:1;}
-
.box div:nth-of-type(2){-webkit-box-flex:2;}
-
.box div:nth-of-type(3){-webkit-box-flex:3;}
-
.box div:nth-of-type(4){-webkit-box-flex:4;}
-
.box div:nth-of-type(5){-webkit-box-flex:5;}
藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務
如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里
打電話分下面4步:
ajax也分下面4步:
下面是原生js寫ajax的具體寫法 :
但是,不能每次用ajax的時候都寫那么多代碼,要把這段ajax代碼封裝起來,方便使用。
封裝ajax代碼如下:
將封裝的ajax調用:
原生js寫ajax可以類比打電話
1.拿出手機
2.撥號
3.說話
4.聽對方說話
1.創建ajax對象
2.連接到服務器
3.發送請求(告訴服務器我要什么文件)
4.接收返回值
藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務
如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里
遮罩層為一張邊框樣式圖(如下圖):
邊框樣式遮罩層顯示在最上方,然后是中間的列表,最下層是一個透明黑色遮罩層,滾動鼠標滾輪,能控制列表滾動
注冊最上面遮罩層的滾動事件,拿到滾動滾動方向,然后控制列表滾動的方向和距離
效果
實現原理
上代碼
藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務注冊事件 /**
* 增加滾輪滾動事件(暫時只實現了chrome的滾動效果)
* @param modalDomId 遮罩層domId
* @param domId 需要滾動下層列表domId
*/ addMousewheelListener(modalDomId:string,domId:string){ //添加頁面監聽 let modalAwardPanel = document.getElementById(modalDomId);
modalAwardPanel.addEventListener('mousewheel',function(e){
let scrollContentDom = document.getElementById(domId); //向上滾 if (e.wheelDelta > 0){ if (scrollContentDom.scrollTop -20 >= 0){
scrollContentDom.scrollTop = scrollContentDom.scrollTop - 20;
} else{
scrollContentDom.scrollTop = 0 ;
}
} //向下滾 else{ if(scrollContentDom.scrollTop + scrollContentDom.clientHeight < scrollContentDom.scrollHeight){
scrollContentDom.scrollTop = scrollContentDom.scrollTop + 20;
}
}
});
}
組件調用: this.addMousewheelListener("你的最上方遮罩層id","你想要滾動的列表id");
如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里
大家都說前端寫頁面較多,幾乎用不到算法。本文愿從彈幕設計這個場景來描述算法在前端中的應用,我們先來看下實現效果:
開場之前我們先來描述彈幕開發的難度,再集中精力描述算法設計的思路。
* 如何保證不同字號的彈幕不碰撞
***如何保證不同字號的彈幕不碰撞***
如果彈幕采用相同的字號,碰撞的問題處理起來比較簡單,只要考慮相鄰彈幕的播放速度和偏移的位置就可以計算出來。然而使用不同字號的彈幕處理起來就麻煩了許多,彈幕的起始位置不可以線性的增加,比如第一行放了字幕,接下來的字幕可以按順序從上至下依次放置即可。
***彈幕的位置計算***
只有設計好彈幕的初始位置,才可以動態、的管理不同字號彈幕的碰撞問題。打個比方,我們通過接口獲取了2秒之內的彈幕數據1000條,每個字幕的長度、速度、字號都不同,怎么管理這些彈幕,示意圖如下:
這是第一種情況,按照從上到啊的順序依次擺放以后會有幾個問題:
一系列問題就不統統列舉出來了,基于這個背景我們結合數學建模的思維方式,找到了彈幕場景相似度非常高的機場運營。我們可以把彈幕當做飛機,每個時間段播放多少彈幕和機場每個時間段放飛多少飛機一個道理。
首都國際機場一共有3條跑道,兩條4E級跑道、一條4F級跑道,2016年的吞吐量為9000萬人次。它的運行機制就是所有飛機通過搭臺有順序的共用3條跑道來完成運輸任務的。
同理,我們也設計了幾個個角色:一個是軌道(跑道)、一個是調度(塔臺)、一個是彈幕(飛機),我們為每個角色設計一個類分為為Track、Main、Bullet。
* 軌道
其次我們來回憶下機場的工作流程:
按照這個思路,我們的彈幕工作流程:
關于軌道的基本原理我們整理清楚了,當然還有不少細節比如如何和調度通信、如何和彈幕通信以及虛擬軌道檢測算法等。有興趣的同學可以參考代碼吧。https://github.com/bytedance/xgplayer/blob/master/packages/xgplayer/src/control/makeBullet.js
* 彈幕
在彈幕啟動之后,首先要檢查本地是否已有緩存數據,沒有的話直接請求數據并緩存,然后執行數據讀取,首次過濾數據進入彈幕隊列,同時啟動定時器。彈幕隊列的數據會定期請求軌道,檢測隊列里的彈幕是否可以進入,一旦確認后軌道做好登記,彈幕就可以進入播放器開啟動畫播放了。定時器每隔2秒就會再次更新數據進入到彈幕隊列(這塊不同的業務可以定制不同的規則)。彈幕播放結束后會通知調度和軌道,調度會在彈幕隊列中移除該彈幕實例,軌道也會移除該彈幕實例的軌道占用。
藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務
圖1.1 彈幕效果
* 彈幕的位置計算
* 彈幕的速度控制及動畫實現
* 彈幕與視頻的同步
圖2.1 彈幕管理示意圖
1. 彈幕五、六、七該怎么計算位置,按top值循環取模+累加嗎?
2. 當彈幕一或者彈幕三足夠長的時候,如何準時的跳過當前位置計算?
3. 當前屏幕的彈幕播放結束,如何再計算的時候利用空出來的位置
4. 空出的位置是否滿足當前彈幕的高度
5. ……
軌道這個角色很重要,它可以解決彈幕位置計算、速度控制、碰撞檢測問題。
首先,我們要來初始化軌道。通俗的說我們要修建幾個跑道呢,我們不是實物,可以動態調整軌道的 數量,計算的原則:
軌道數量 = 播放器有效高度 / 設備基準字號
* 播放器有效高度:播放器的實際高度減去控制條的高度,因為彈幕不可以遮擋控制條。
* 設備基準字號:移動端是10px,pc端是12px;
為啥計算公式是這樣的?因為我們要支持不同字號的彈幕。試想不同的字號對物理空間的占用是不同的,然而如果要求軌道的尺寸是動態的,那就帶來很復雜的計算。本文提出“虛擬軌道”的概念,在交通管制中最常見的就是道路合并或者改向。我們也是采用將相鄰的物理軌道臨時合并為一條軌道。這樣就可以輕松的解決不同字號的軌道占用問題。原理圖如下:
圖2.2 軌道計算示意圖
1. 機長呼叫塔臺,CZ6132請求起飛
* 目前跑道均被占用,請等待
* N時刻后再次執行步驟1
* 目前跑道 A1 空閑,準許進入
* 執行步驟3
2. 塔臺查看跑道使用情況
3. 進入跑道,起飛完成
4. 機長通知塔臺,本次起飛完成,釋放跑道的占用
5. 其他飛機同樣執行上述步驟
1. 彈幕進入播放器
2. 軌道根據彈幕的播放速度、尺寸計算是否有合適的軌道提供
* 沒有
* 通知彈幕尚無合適軌道提供,請等待;同時,彈幕隊列中的其他彈幕依次執行步驟1
* 有
* 執行步驟3
3. 播放器加載彈幕DOM,開始播放,待播放完成
4. 播放完成通知軌道更新軌道占用情況
5. 其他彈幕同樣執行上述步驟
圖2.3 軌道可用性計算示意圖
彈幕基本是實現“飛機”的角色,我們要求它具有自身的屬性和方法。比如調度中心通過id能拿到它所有的基本信息,軌道控制也可以通過彈幕進行檢查和更新。當然彈幕也必須具備狀態自動更新、移動、播放結束通知、自動銷毀等功能。
* 調度
調度就是搭臺的化身,承接著軌道、彈幕的控制,也保持著與播放器的步調一致。它的職責如下:
1. 播放器交互控制
2. 彈幕隊列控制
3. 自身狀態更新
4. 數據格式轉換
5. 動畫執行
還是直接用流程圖來描述更直接些:
圖2.4 彈幕運行機制流程圖
如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里
一.寫在前面
1.為什么要學小程序開發?
對于前端開發而言,微信小程序因為其簡單快速、開發成本低、用戶流量巨大等特點,也就成了前端開發工程師必會的一個技能。
2.開發準備:
(1)有人開玩笑說,會vue小程序根本都不用學:
微信小程序雖然是騰訊自己搞的,但是核心的思想跟vue等框架是一樣一樣的哦~
(2)善于搜集精美的小組件: “我們不生產代碼,我們只是代碼的搬運工”,善于找到想要的組件并把他們巧妙優雅的組裝成一個大項目,也算是程序員一項基本技能了。
具體怎么找到想要的小程序demo,篇末會給大家推薦小程序的資源,有很多大神的項目哦
擼起袖子開干了
一.注冊小程序賬號,下載IDE
1.官網注冊https://mp.weixin.qq.com/,并下載IDE。
2.官方文檔一向都是最好的學習資料。
注意:
(1)注冊賬號之后會有一個appid,新建項目的時候需要填上,不然很多功能是用不了的,比如不能預覽,不能上傳代碼等等。
(2)如果你注冊過微信公眾號的話,一定要注意,微信公眾號和小程序是兩個賬號,二者的appid也是不同,小程序開發必須使用小程序的appid哦。
二.小程序框架介紹和運行機制
1.我們建立了“普通快速啟動模板”,然后整個項目目錄如下:
2.app.js
整個項目的啟動文件,如注釋寫的onlaunch方法有三大功能,瀏覽器緩存進行存和取數據;用登陸成功的回調;獲取用戶信息。
globalData是定義整個項目的全局變量或者常量哦。
3.app.json
整個項目的配置文件,比如注冊頁面,配置tab頁,設置整個項目的樣式,頁面標題等等;
!注意:小程序啟動默認的第一個頁面,就是app.json的pages中的第一個頁面哦。
4.pages
小程序的頁面組件,有幾個頁面就會有幾個子文件夾。比如快速啟動模板,就有兩個頁面,index和logs
5.打開index目錄
可以看到有三個文件,其實和我們web開發的文件是一一對應的。
index.wxml對應index.html;
index.wxss對應index.css;
index.js就是js文件哦。
一般我們還會給每個頁面組件添加一個.json文件,作為該頁面組件的配置文件,設置頁面標題等功能
6.雙擊index.js文件
(1)var app = getApp();
引入整個項目的app.js文件,用來取期中的公共變量等信息。
如果要使用util.js工具庫中的某個方法,在util.js中module.exports導出,然后在需要的頁面中require即可得到哦。
(2)比如,我們要獲取豆瓣電影的時候,我們需要調用豆瓣的api;我們先在app.js中的gloabData中定義doubanBase
然后在index.js中使用app.globaData.doubanBase即可取到這個值。
當然這些常量你也可以在頁面需要的時候,再用寫死的值,但是為了整個項目的維護,還是建議把這種公用參數統一寫在配置文件中哦。
(3)接下來在整個page({})中,第一個data,就是本頁面組件的內部數據,會渲染到該頁面的wxml文件中,類似于vue、react哦~
通過setData修改data數據,驅動頁面渲染
(4)一些生命周期函數
比如onload(), onready(), onshow(), onhide()等等,監聽頁面加載、頁面初次渲染、頁面顯示、頁面隱藏等等
更多的可以查官網API哦。其中用的最多的就是onload()方法,和onShareAppMessage()方法(設置頁面分享的信息)
7 .wxml模板的使用。
比如本項目電影頁面,就是以最小的星級評價組件wxml當做模板,star到movie到movie-list,一級一級的嵌套使用。
star-template.wxml頁面寫好name屬性;然后import引入的時候通過name獲得即可
8.常用的wxml標簽
view,text,icon,swiper,block,scroll-view等等,這些標簽直接查官網文檔即可
三.小程序框架、各個頁面以及發布上線的注意點
1.整個框架中的一些注意點
(1)整個wxml頁面,最底層的標簽是哦。
(2) 每個頁面頂部導航欄的顏色,title在本頁面的json中配置,如果沒有配置的話,取app.json中的總配置哦。
(3)json中不能寫注釋哦,不然會報錯的。
(4)路由相關
1)使用wx.SwitchTab跳轉tab頁的話,在app.json中除了注冊pages頁面,還需要在tabBar中注冊tab頁,才能生效哦。
注意:tab最多5個,也就是我們說的頭部或者底部最多5個菜單。其他的頁面只能通過其他路由方法打開哦。
2)navigateTo是跳到某個非tab頁,比如歡迎頁,電影詳情頁,城市選擇頁;在app.json中注冊后,不能在tabBar里注冊哦,不然同樣也是不能跳轉的哦。
3)reLaunch跳轉,新開的頁面左上角是沒有退回按鈕的,本項目只用了一次,切換城市的時候哦。
(5)頁面之間傳遞參數
參數寫在跳轉的url之中,然后另一個頁面在onload方法中的傳參option接收到。如下傳遞和獲取id
(6)data-開頭的自定義屬性的使用
比如wxml中我們怎么寫
點擊的事件對象可以這么取,var postId = event.currentTarget.dataset.postid;
注意: 大寫會轉換成小寫,帶_符號會轉成駝峰形式
(7)事件對象event,event.target和event.currentTarget的區別:
target指的是當前點擊的組件 和currentTarget 指的是事件捕獲的組件。
比如,輪播圖組件,點擊事件應該要綁定到swiper上,這樣才能監控任意一張圖片是否被點擊,
這時target這里指的是image(因為點擊的是圖片),而currentTarget指的是swiper(因為綁定點擊事件在swiper上)
(8)使用免費的網絡接口:
本項目中用到了 和風天氣api,騰訊地圖api,百度地圖api,豆瓣電影api,聚合頭條新聞api等,具體用法可以看各自官網的接口文檔哦,很詳細的
注意:免費接口是有訪問限制的,所以如果用別人的組件用了這種接口的話,最好還是自己注冊一個新的key替換上哦
附上一個免費接口大全:
https://github.com/jokermonn/-Api
??!另外還要注意,要把這些接口的域名配置到小程序的合法域名中,不然也是訪問不了的
(8)wxss有一個坑:無法讀取本地資源,比如背景圖片用本地就會報錯哦。
把本地圖片弄成網絡圖片的幾種方式: 上傳到個人網站;QQ空間相冊等等也是可以的哦
2.切換城市頁面:
(1)首頁使用navigateTo跳轉到切換城市頁,由于首頁并沒有關閉,導致切換了城市返回來,天氣信息還是舊的。
正確的處理邏輯如下:
1)使用reLaunch跳轉到切換城市頁面,實質是關閉所有頁面打開新的頁面哦。
2)切換城市頁面,更新公共變量中城市信息為手動切換的城區,再switchTab回到首頁,觸發首頁重新加載。
3)首頁獲取城市信息的時候加一個判斷,全局沒有才取定位的,全局有(比如剛才設置了)就用全局的哦。
(2)城市列表的滾動和回到頂部
基于scroll-view組件的scroll-top屬性,初始就是0,滾動就會增加的;點擊回到頂部給它置為0即可回到頂部
3.天氣頁
(1)初始化頁面,天氣顯示的邏輯
首先調用小程序的wx.getLocation方法獲得當前的經緯度,然后調用騰訊地圖獲得當前的城市名稱和區縣名稱,并存到公共變量中,
再調用查詢天氣和空氣質量的方法哦。
(2)容錯處理
城市的名稱長短不一,有點名字特別長,比如巴彥淖爾市這種,需要動態的獲取完整的城市名稱;
有些偏僻的城市暫時沒有天氣信息,我們需要對返回的結果進行判斷,沒有信息的需要給用戶一個良好的提示信息。
4.周邊-地圖服務頁面
(1)調用百度地圖的各種服務,查詢酒店,美食,生活服務三種信息,更多信息可以看百度地圖的文檔
(2)點擊時給被點中的圖標加個邊框,數據驅動視圖,所以使用一個長度為3的數組保存三個圖標當前是否被點中的狀態
然后wxml再根據數據來動態添加class,增加邊框樣式
5.豆瓣電影頁
(1)電影詳情頁的預覽圖片,用小程序本身的previewImage實現。
(2)詳情頁使用onReachBottom()方法,監控用戶上拉觸底事件,然后發送請求繼續獲得數據,實現懶加載的效果
(3)用戶體驗方面的優化,js中將整數評分比如7分統一改為7.0分,然后wxml模板再判斷分數是否為0顯示“暫無評分”
(4)搜索之后清空搜索框
因為小程序中不能使用getelementbyId這種方式獲得元素,只能用數據來控制了
在data中加一個屬性searchText來保存搜索框的內容并和 input的value屬性綁定,搜索完成或者點擊X時,searchText變量清空即可實現清空輸入框的效果哦。
6.新聞頁面
(1)聚合頭條新聞的免費接口,只返回了新聞的基本信息,新聞的主體內容是沒有的哦。
我找了好多新聞類的接口,好像都是沒有新聞主體內容的。如果誰知道更好的接口歡迎留言告訴我哈~
(2)當然,也可以自己去爬新聞網站的數據哦
7.更多頁面
(1)小程序目前開放外鏈的功能只是給公司組織的小程序開放了,個人開發還是不能使用外鏈的哦。
(2)彩蛋頁面,獲得用戶信息
通過 wx.setStorageSync('userInfos', userInfos); 可以獲得登陸小程序的用戶的個人信息,可以發送給后臺存到數據庫中,方便對用戶進行分析
我這里只是存儲到瀏覽器緩存中哦,最大應該是10M緩存;如果用戶把這個小程序從小程序列表中刪除掉,就會清空這個緩存。
8.發布注意
(1) 新版本小程序發布的限制為2M,一般都是圖片最占空間,所以盡量使用網絡圖片
具體怎么把本地圖片變成網絡圖片,上面有講哦。
(2)在開發者工具上預覽測試沒問題,點擊上傳;網頁版小程序個的人中心的左側“開發管理”菜單,第三塊--開發版本就有了內容。
(3)點擊提交,填寫小程序相關信息,就可以提交審核了哦。
注意:分類最好填寫準確,這樣才能更快的通過審核哦。我這個小程序一天半時間過審上線的
至此,我就把兩天開發內碰到的坑和注意點都過了一遍,據說還有更多的坑,等之后更深入的開發再繼續研究咯。
小程序學習資料
藍藍設計的小編 http://www.syprn.cn