html5

html5新特性

新的選擇器

querySelector

選擇一個(如果多個匹配返回第一個)

document.querySelector('#div');
document.querySelector('.div');
document.querySelector('div');

querySelectorAll

選擇多個

getElementsByClass

JSON

JSON.parse

把json格式的字符串轉化為js對象

json格式

{
    "key":"value",
    "key2": 1, 
}

注意: 鍵值必須加雙引號, 如果值是字符串,也必須加雙引號

var str = '{"key": "value"}';
var obj = JSON.parse(str);

JSON.stringify

把js對象轉化為json格式的字符串

使用JSON.parse和JSON.stringify做深拷貝

function deepCopy(obj){
    var str = JSON.stringify(obj);
    return JSON.parse(str);
}

var obj = { a: 1 };

var objClone = deepCopy(obj);

objClone.a = 2;

console.log(obj.a);//1

data自定義數據

在html元素上以data-開頭的屬性,可以在相應的DOM對象上的dataset屬性上得到其屬性值

<div data-index="1" data-sub-title="hello"></div>
var oDiv = document.querySelector('div');
console.log( oDiv.dataset.index );//1
console.log( oDiv.dataset.subTitle );//hello  sub-title這樣的多個-分割的形式,對應的屬性為駝峰命名

js加載

defer

延遲加載

<script src="a.js"></script>
<script src="b.js"></script>
<script src="c.js"></script>
<img src="" alt="">

默認js的加載是順序執行的,先加載js才會加載圖片

<script src="a.js" defer="defer"></script>
<script src="b.js"></script>
<script src="c.js"></script>
<img src="" alt="">

如果script標簽加上defer屬性表示延遲加載(在onload之間加載),也就是說a.js會在圖片加載之后加載

沒加defer的js依然順序加載

<script src="a.js" defer="defer"></script>
<script src="b.js" defer="defer"></script>
<script src="c.js" defer="defer"></script>
<img src="" alt="">

等價于

<img src="" alt="">
<script src="a.js"></script>
<script src="b.js"></script>
<script src="c.js"></script>

async

異步加載

<script src="a.js" async="async"></script>
<script src="b.js" async="async"></script>
<script src="c.js" async="async"></script>
<img src="" alt="">

表示幾個js文件和圖片會同時加載

問題: 不能確定那個js文件先加載完成(適合獨立js的加載)

歷史管理 history

觸發歷史管理:

  1. 跳轉頁面
  2. 改變hash
  3. pushState

onhashchange事件

當hash值發生改變時出發

例子: 彩票選擇

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<button>隨機選擇</button>
<div></div> 
<script>
var oDiv = document.querySelector('div');
var btn = document.querySelector('button');

var json = {};

btn.onclick = function(){
    var hash = Math.random();
    var arr = randomArr(35, 7);
    json[ hash ] = arr;
    oDiv.innerHTML = arr.join(',');
    window.location.hash = hash;
}
window.onhashchange = function(){
    var hash = window.location.hash.slice(1);
    oDiv.innerHTML = json[hash];
}
function randomArr(maxNum , length){
    var arr = [];
    for(var i=0;i<length;i++){
        arr.push( parseInt(Math.random()*maxNum) )
    }
    return arr;
}
</script>
</body>
</html>

history.pushState 和 onpopstate事件

history.pushState

有三個參數:state對象,標題(現在是被忽略,未作處理),URL(可選)

當history實體被改變時(后退或前進),popstate事件將會發生

如果history實體是有pushState方法產生的,popstate事件的state屬性會包含一份來自history實體的state對象的拷貝

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<button>隨機選擇</button>
<div></div> 
<script>
var oDiv = document.querySelector('div');
var btn = document.querySelector('button');

var json = {};

btn.onclick = function(){
    var arr = randomArr(35, 7);
    history.pushState(arr, '');
    oDiv.innerHTML = arr.join(',');
}
window.onpopstate = function(ev){
    oDiv.innerHTML = ev.state.join(',');
}
function randomArr(maxNum , length){
    var arr = [];
    for(var i=0;i<length;i++){
        arr.push( parseInt(Math.random()*maxNum) )
    }
    return arr;
}
</script>
</body>

拖放

在html標簽上設置draggable="true", 元素久可以拖拽了

<div draggable="true"></div>

但是拖拽有點奇怪, 元素本身不會移動, 感覺是影子在移動, 跟拖拽圖片的效果很像

拖拽元素事件
  • dragstart 拖拽前觸發
  • drag 拖拽前、拖拽結束之間,連續觸發
  • dragend 拖拽結束觸發
<style>
.drag{
    width: 100px;
    height: 100px;
    background: red;
}
</style>
<div class="drag" draggable="true"></div>
<script>
    var oDrag = document.querySelector('.drag');
    oDrag.ondragstart = function(){
        this.style.background = 'green';
    }

    oDrag.ondragend = function(){
        this.style.background = 'red';
    }
    var i=0;
    oDrag.ondrag = function(){
        document.title = i++;
    }
</script>
目標元素事件
  • dragenter , 進入目標元素觸發
  • dragover ,進入目標、離開目標之間,連續觸發
  • dragleave , 離開目標元素觸發
  • drop , 在目標元素上釋放鼠標觸發(需要在dragover事件中阻止默認行為才能生效)
<style>
div{
    width: 100px;
    height: 100px;
}
.drag{
    background: red;
}
.target{
    background: green;
}
</style>
<div class="drag" draggable="true"></div>
<div class="target"></div>
<script>
var oTarget = document.querySelector('.target');
oTarget.ondragenter = function(){
    this.style.background = '#111';
}
var i=0;
oTarget.ondragover = function(ev){
    ev.preventDefault();
    document.title = i++;
}
oTarget.ondragleave = function(){
    this.style.background = 'green';
}
oTarget.ondrop = function(){
    alert(1)
}
</script>
事件的執行順序

drop不觸發的時候:

dragstart > drag > dragenter > dragover > dragleave > dragend

drop觸發的時候(dragover的時候阻止默認事件):

dragstart > drag > dragenter > dragover > drop > dragend

火狐下拖拽的問題

只設置draggable屬性,在火狐下還是不能拖拽

還必須設置在dragstart事件中,設置dataTransfer對象上的setData方法才能拖拽除圖片以外的其他元素

<div class="drag" draggable="true"></div>
<script>
var oDrag = document.querySelector('.drag');
oDrag.ondragstart = function(ev){
    ev.dataTransfer.setData('key', 'value');
}
</script>
dataTransfer

在拖拽事件中,是事件對象上的一個屬性

有兩個方法:

  • setData(key, value) key,value必須都是字符串
  • getData(key)
var oDrag = document.querySelector('.drag');
oDrag.ondragstart = function(ev){
    ev.dataTransfer.setData('a', 'b');
    alert(ev.dataTransfer.getData('a'));//b
}

實例: 將li拖拽到div, 在ondrop是刪除對應的li

<style>
    div{
        width: 100px;
        height: 100px;
        background: red;
    }
    .drag{
        background: red;
    }
    .target{
        background: green;
    }


    li{
        display: inline-block;
        background: yellow;
    }
</style>
<ul>
    <li draggable="true">aa</li>
    <li draggable="true">bb</li>
    <li draggable="true">cc</li>
</ul>

<div>
    
</div>
<script>
var aLi = document.querySelectorAll('li');
var oDiv = document.querySelector('div');
aLi.forEach(function(elem, i){
    elem.i = i;
    elem.ondragstart = function(ev){
        ev.dataTransfer.setData('index', this.i);
    }


});
oDiv.ondragover = function(ev){
    ev.preventDefault();
}
oDiv.ondrop = function(ev){
    var i = ev.dataTransfer.getData('index');
    aLi[i].remove();
}
</script>
dataTransfer.effectAllowed

移入目標元素時,鼠標的樣式

取值: none, copy, copyLink, copyMove,link,linkMove,move, all,uninitialized

oDrag.ondragstart = function(ev){
    ev.dataTransfer.effectAllowed = 'link';
}
dataTransfer.setDragImage()

三個參數: 指定的元素, 坐標x, 坐標y

oDrag.ondragstart = function(ev){
    ev.dataTransfer.setDragImage(oDiv, 0, 0);
}
dataTransfer.files

獲取外部拖拽的文件, 返回一個filesList列表

filesList下每個文件對象有個type屬性, 返回文件的類型

關于外部文件的拖拽, 這樣我們就不需要操作拖拽元素了, 只需要操作目標元素

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
<style>
div{
    width: 200px;
    height: 200px;
    background: red;
}
</style>
</head>
<body>
    <div>將文件拖放到此區域</div>
<script>
var oDiv = document.querySelector('div');
oDiv.ondragenter = function(ev){
    this.innerHTML = '可以釋放了';
    console.log(ev.dataTransfer.files[0].type);
}
oDiv.ondragover = function(ev){
    ev.preventDefault();
};
oDiv.ondragleave = function(){
    this.innerHTML = '將文件拖放到此區域';
}
oDiv.ondrop = function(ev){
    ev.preventDefault();//阻止瀏覽器的默認行為, 默認拖放文件到瀏覽器,會將文件在瀏覽器中打開
};
</script>
</body>
</html>
FileReader

使用FileReader對象,web應用程序可以異步的讀取存儲在用戶計算機上的文件(或者原始數據緩沖)內容

  • fd.readAsDataURL(file);

data: URL格式的字符串以表示所讀取文件的內容
參數為file對象,在拖拽中可以是ev.dataTransfer.files[0];

  • fd.onload

讀取文件成功的回調函數,

成功獲fd對象的result屬性代表了獲取的文件數據, 如果是圖片,則返回base64格式的圖片數據

oDiv.ondrop = function(ev){
    ev.preventDefault();
    var fd = new FileReader();
    fd.readAsDataURL(ev.dataTransfer.files[0]);
    fd.onload=function(){
        console.log(this.result);
    }
};

或者在<input>

<input id="fileItem" type="file">
<script>
var fileItem = document.getElementById('fileItem');
fileItem.onchange = function(){
    var file = this.files[0];
    var fd = new FileReader();
    fd.readAsDataURL(file);
    fd.onload=function(){
        console.log(this.result);
    }
}
</script>

實例: 圖片預覽

<div>將文件拖放到此區域</div>
<ul></ul>
<script>
var oDiv = document.querySelector('div');
var oUl = document.querySelector('ul');
oDiv.ondragenter = function(ev){
    this.innerHTML = '可以釋放了';
}
oDiv.ondragover = function(ev){
    ev.preventDefault();
};
oDiv.ondragleave = function(){
    this.innerHTML = '將文件拖放到此區域';
}
oDiv.ondrop = function(ev){
    ev.preventDefault();
    var files = ev.dataTransfer.files;
    files = [].slice.call(files);
    files.forEach(function(file, i){
        if( file.type.indexOf('image')!=-1){
            var li = document.createElement('li');
            var img = document.createElement('img');
            li.appendChild(img);

            var fd = new FileReader();
            fd.readAsDataURL(file);
            fd.onload = function(){ 
                img.src= this.result;
                oUl.appendChild(li);

            }   
        }
        else{
            alert('請選擇圖片格式');
        }
        
    });


};
</script>

實例: 拖拽購物車

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
<style>
#cart{
    border: 1px solid  #111;
    min-height: 500px;
    min-width: 300px;
}
</style>
</head>
<body>

<ul id="product-list">
</ul>
<ul id="cart"></ul> 
<script>
var products = [
    {
        img: 'http://g-search2.alicdn.com/img/bao/uploaded/i4/i2/TB1wSUANpXXXXXeXXXXXXXXXXXX_!!0-item_pic.jpg_80x80.jpg',
        title: 'i7 6850K/華碩X99/GTX1080 VR游戲',
        price: 10000
    },
    {
        img: 'http://g-search3.alicdn.com/img/bao/uploaded/i4/i2/TB1UdPeOFXXXXa_XFXXXXXXXXXX_!!0-item_pic.jpg_80x80.jpg',
        title: '松明微星宙斯盾Aegis B903-008CN i7/8G*2/GTX1070臺式機',
        price: 9999
    },
    {
        img: 'http://g-search1.alicdn.com/img/bao/uploaded/i4/i1/TB1UOY_KpXXXXciXVXXXXXXXXXX_!!2-item_pic.png_80x80.jpg',
        title: '海盜船 夢幻電腦250D 6700K/1151 多屏炒股HTPC辦公臺式電腦主機',
        price: 8888
    }

]

var cartData = {};

var str = '';

products.forEach(function(product, i){
    str += `
    <li draggable="true" data-index="${i}">
        ![](${product.img})
        <p>${product.title}</p>
        <p>¥${product.price}</p>
    </li>

    `
});

var oProduct = document.querySelector('#product-list');
var oCart = document.querySelector('#cart');

oProduct.innerHTML = str;

var aProductItem = document.querySelectorAll('#product-list li');

aProductItem.forEach(function(product, i){
    product.ondragstart = function(ev){
        ev.dataTransfer.setDragImage(this,0, 0);
        console.log(this.dataset.index);
        ev.dataTransfer.setData('index', this.dataset.index);
    }
});

oCart.ondragover = function(ev){
    ev.preventDefault();
}

oCart.ondrop = function(ev){
    ev.preventDefault();
    var index = ev.dataTransfer.getData('index');
    var product = products[index];
    var cartItem = null;

    if( !cartData[index] ){
        cartItem = {
            title: product.title,
            price: product.price,
            count: 1,
            li: document.createElement('li')
        }
        cartData[index] = cartItem;
        oCart.appendChild(cartItem.li);           
    }
    else{
        cartItem = cartData[index];
        cartItem.count++;
        
    }

    cartItem.li.innerHTML = `
        <span class="count">${cartItem.count}</span>
        <span class="title">${cartItem.title}</span>
        <span class="total">¥${cartItem.price*cartItem.count}</span>
    `;

}
</script>
</body>
</html>

canvas

基本使用

<!--不要使用css給canvas設置寬高-->
<canvas id="canvas" width="500" height="300">
        你的瀏覽器不支持canvas
</canvas>

繪圖環境

var canvas = document.querySelector('#canvas');
var context = canvas.getContext('2d');

目前只支持2d,不支持3d,如果要使用3d, 可以使用webgl(不過兼容性也不是很好)

繪制方塊

context.fillRect

context.fillRect(left,top, width, height)

context.fillRect(50,50, 100, 200);

默認顏色是黑色

context.strokRect

strokeRect(left, top, width, height)

context.strokeRect(50,50, 100, 200);

默認是1像素黑色邊框

但是顯示出在ps中測量為2像素的邊框,把畫布看成一個坐標軸,正方形的頂點坐標為(50px, 50px)

正方形的邊框為1像素寬,我們以左邊框為例, 它是以50px為中心點,向右延伸0.5像素(49.5px),
向左延伸0.5像素(50.5px); 所以做邊框為(49.5px~50.5px)

但是,用canvas繪圖跟我們的ps一樣, 最小的但是就是1px,沒有0.5px, 所以就將出現了2px的邊框

我們可以這樣寫

context.strokeRect(50.5,50.5, 100, 200);

這樣邊框的中心點在1px的一半,剛剛就可以是1px

設置繪圖

fillStyle 填充顏色

strokeStyle 邊框顏色

lineWidth 線寬

context.fillStyle = 'red';
context.strokeStyle = 'blue';
context.lineWidth = 10;


//注意: 順序不同,效果不同
context.fillRect(50,50,100,50);
context.strokeRect(50,50,100,50);

邊界繪制

lineJoin 邊界連接點樣式

miter(默認)(斜接) round(圓角) bevel(斜角)

lineCap 端點樣式

butt(默認) round(圓角) square()

繪制路徑

beginPath

closePath

moveTo

lineTo

stroke

fill

rect

clearRect

save

restore

實例: 鼠標畫線

var canvas = document.querySelector('#canvas');
var context = canvas.getContext('2d');
canvas.onmousedown = function(ev){
    context.moveTo(ev.clientX - canvas.offsetLeft, ev.clientY-canvas.offsetTop)
    canvas.onmousemove = function(ev){
        context.lineTo(ev.clientX - canvas.offsetLeft, ev.clientY-canvas.offsetTop);
        context.stroke();
    }
    canvas.onmouseup = function(){
        this.onmousemove = null;
        this.onmouseup = null;
    }
}

實例: 方塊移動

var canvas = document.querySelector('#canvas');
var context = canvas.getContext('2d');
var iNow = 0;
setInterval(function(){
    iNow++;
    context.clearRect(0, 0, 500, 300);
    context.fillRect(iNow, iNow, 100, 100);

}, 50);

繪制圓

arx(x, y, 半徑, 起始弧度, 終止弧度, 旋轉方向)

  • 弧度與角度的關系: 弧度=角度*Math.PI/180
  • 旋轉方向: 順時針false(默認), 逆時針true

實例: 時鐘

var canvas = document.querySelector('#canvas');
var context = canvas.getContext('2d');

var r = 100;
var x = 150;
var y = 150;
function drawClock(){
    context.clearRect(0, 0, 500, 300);
    var now = new Date();
    var hour = now.getHours();
    var min = now.getMinutes();
    var sec = now.getSeconds();

    console.log(hour, min, sec);

    var hourAngle = hour*30 + min*(30/60) - 90;
    var minAngle = min*6+sec*(6/60) - 90;
    var secAngle = sec*6 -90;

    //分鐘刻度
    for(var i=0;i<60;i++){
        context.beginPath();
        context.moveTo(x,y);
        context.arc(x,y,r, 6*i*Math.PI/180, 6*(i+1)*Math.PI/180);
        context.stroke();
        context.closePath();
    }

    context.beginPath();
    context.fillStyle ='white';
    context.arc(x,y,r*(19/20), 0, 360*Math.PI/180);
    context.fill();
    context.closePath();

    // 時鐘刻度
    for(var i=0;i<12;i++){
        context.beginPath();
        context.lineWidth = 3;
        context.moveTo(x,y);
        context.arc(x,y,r, 30*i*Math.PI/180, 30*(i+1)*Math.PI/180);
        context.stroke();
        context.closePath();
    }

    context.beginPath();
    context.fillStyle ='white';
    context.arc(x,y,r*(17/20), 0, 360*Math.PI/180);
    context.fill();
    context.closePath();


    // 時鐘指針
    context.beginPath();
    context.moveTo(x,y);
    context.arc(x,y,r*(12/20), hourAngle*Math.PI/180, hourAngle*Math.PI/180);
    context.stroke();
    context.closePath();

    // 分鐘刻度
    context.beginPath();
    context.moveTo(x,y);
    context.arc(x,y,r*(14/20), minAngle*Math.PI/180, minAngle*Math.PI/180);
    context.lineWidth = 2;
    context.stroke();
    context.closePath(); 

    // 秒鐘刻度
    context.beginPath();
    context.moveTo(x,y);
    context.arc(x,y,r*(17/20), secAngle*Math.PI/180, secAngle*Math.PI/180);
    context.lineWidth = 1;
    context.stroke();
    context.closePath();    
}

drawClock();


setInterval(function(){
    drawClock();
}, 1000);
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,622評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,716評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,746評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,991評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,706評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,036評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,029評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,203評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,725評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,451評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,677評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,161評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,857評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,266評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,606評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,407評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,643評論 2 380

推薦閱讀更多精彩內容