Giter VIP home page Giter VIP logo

javascript30's Introduction

JavaScript30

這是 30 個在 30 天內用 JavaScript 寫的網站練習,我也有紀錄平時寫的 HTML/CSS 練習作品在這個 Repo。關於這個 JavaScript30 的挑戰,我把完成後的心得與一些想法整理於Medium,歡迎與我交流 :)

01 - JavaScript Drum Kit

Demo

  • transitionend 事件

    • 在 CSS transition 結束後觸發,搭配 remove class 可以做出按鍵被按之後的閃爍效果
  • querySelector 尋找 dataset attribute 符合

    querySelector(`div[data-key="${e.keyCode}"]`)
    • div[data-key${matching}] 可以直接在 querySelector 找到特定 node
  • <audio data-key="65" src="sounds/clap.wav"></audio>

    • 聲音檔案在 Html 上用 audio 包住,src 指定檔案來源
    // 從頭播放
    audio.currentTime = 0;
    audio.play();

02 - JS and CSS Clock

Demo

  • transform-origin CSS 屬性

    • 參數:x-axis y-axis z-axis
  • transition-timing-function CSS 屬性

    • 製造指針擺動效果

    transition-timing-function: cubic-bezier(0.1, 2.7, 0.58, 1);

03 - CSS Variables

Demo

  • CSS Varialbes

    • 宣告
    :root {
        --spacing: 10px;
        --blur: 10px;
        --base: #8282e6;
    }
    • 使用
    img {
        padding: var(--spacing);
        background: var(--base);
        filter: blur(var(--blur));
    }
  • JS 變更 CSS Variables

    • HTML Input tag
     <label for="blur">Blur:</label>
     <input id="blur" type="range" name="blur" min="0" max="25" value="10" data-sizing="px">
    
     <label for="base">Base Color</label>
     <input id="base" type="color" name="base" value="#8282e6">
    • JS event function
    inputs.forEach((input) => input.addEventListener('change', updateCSS));
    
    inputs.forEach((input) => input.addEventListener('mousemove', updateCSS));
    
    function updateCSS() {
        const suffix = this.dataset.sizing || '';
        document.documentElement.style.setProperty(`--${this.name}`, this.value + suffix);
    }
  • HTML <input> 參數

04 - Array Cardio Day 1

Demo

  • Filter

    回傳符合條件的元素組成的陣列

    const fifteen = inventors.filter(inventor => (inventor.year >= 1500 && inventor.year < 1600))
  • map

    回傳透過函式內回傳的值組合成一個陣列

    const fullName = inventors.map((inventor) => inventor.first + ' ' + inventor.last);
  • sort

    回傳符合條件排序後的陣列

    const ordered = inventors.sort((first, second) => first.year > second.year ? 1 : -1);
    
    const sorted = inventors.sort((first, second) => {
        const lastPerson = first.passed - first.year;
        const nextPerson = second.passed - second.year;
        return lastPerson > nextPerson ? -1 : 1;
    });
    
    const alpha = people.sort((a, b) => {
        const [aLast, aFirst] = a.split(", ");
        const [bLast, bFirst] = b.split(", ");
        return aLast > bLast ? 1 : -1;
    });
  • reduce

    與前一個回傳的值再次作運算,詳細使用為: array.reduce(reducer[accumlator, currentValue, currentIndex, array], initialValue)

    const totalYears = inventors.reduce((total, inventor) => {
        return total + (inventor.passed - inventor.year);
    }, 0);
    
    const data = ['car', 'car', 'truck', 'truck', 'bike', 'walk', 'car', 'van', 'bike', 'walk', 'car', 'van', 'car'];
    const transport = data.reduce((obj, item) => {
        if (!obj[item]) {
            obj[item] = 0;
        }
        obj[item]++;
        return obj;
    }, {});
  • tips

    • 用 console.table 可以把陣列用 table 方式 log 到瀏覽器的 console

05 - Flex Panel Gallery

Demo

  • display: flex
    • 本身為 flex 的元素為 flex-box,而其子元素為 flex-item
  • flex: flex-grow flex-shrink flex-basis
    • flex 決定 flex-item 如何分配 flex-box 的剩餘空間
    • flex-grow、flex-shrink 數值皆為相對概念
      • 大於 0 即會分配剩餘空間
      • flex: 5 為 flex: 1 的五倍大
      • grow 決定分配剩餘,shrink 決定如何縮減多餘
  • transition-timing-function 先縮後放效果
    • 效果參數為:cubic-bezier(0.61, -0.19, 0.7, -0.11)
  • classList.toggle(className)
    • 在元素切換一個 CSS,有則 remove(),無則 add()
  • transitionend event
    • 監聽 transition 結束時觸發,可用 e.propertyName 抓到 transition 的事件
    • 搭配指定 e.propertyName 條件,可以把多個 transition 串起來
  • includes
    • flex 變化在 chrome 為 flex-grow 事件,在 safari 為 flex 事件,可用 if (e.propertyName.includes('flex')) 解決

06 - Type Ahead

Demo

  • fetch()

    • Fetch 為替代XMLHttpRequest 的方案
    • fetch(url) 本身會回傳一個 Promise 物件,與 jQuery.ajax() 不同點在於,當接收到一個代表錯誤的 HTTP 狀態碼時,從fetch()返回的 Promise 不會被標記為 reject, 即使該 HTTP 的狀態碼是 404 或 500。相反,它會將 Promise 狀態標記為 resolve (但是會將 resolve 的返回值的 ok 屬性設置為 false ),僅當網絡故障時或請求被阻止時,才會標記為 reject
    • fetch() 的處理可以用 .then() 串接,會得到 response
    fetch(url)
        .then((blob) => blob.json())
        .then((data) => cities.push(...data));
    • blob 命名為 Binary Large Object 的縮寫,通常表一個相當於檔案( Raw data )的不可變物件
    • .json() 是 response 的 method
    • 把回傳陣列裡的物件裡各自塞入大陣列可以直接用 .push(...data)
  • 即時監聽 <input> 有無變化需要同時監聽兩個事件

    • change
    • keyup
  • 把 array 裡的物件轉成 HTML 的方法

    • for loop

    • map + return + .join('')

      function displayMatches() {
          const matchArray = findMatches(this.value, cities);
          const html = matchArray
              .map((place) => {
                  return `
              <li>
                <span class="name">${cityName}, ${stateName}</span>
                <span class="population">${numberWithCommas(place.population)}</span>
              </li>
            `;
              })
              .join('');
          suggestions.innerHTML = html;
      }
    • .join('') 是為了把大陣列轉成一個字串

  • RegExp(wordToMatch, 'gi')

    • g modifier: global. All matches (don't return on first match)
    • i modifier: insensitive. Case insensitive match (ignores case of [a-zA-Z])
    • .match(regex) 返回符合的值
    • .replace(regex, replacingWord) 返回替代後的值
  • 為數字加分隔號

    function numberWithCommas(x) {
        return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
    }
  • 例子(把 Array 變成 Html,把其中相符的值變色)

    function displayMatches() {
        const matchArray = findMatches(this.value, cities);
        const html = matchArray
            .map((place) => {
                const regex = new RegExp(this.value, 'gi');
                const cityName = place.city.replace(regex, `<span class="hl">${this.value}</span>`);
                const stateName = place.state.replace(regex, `<span class="hl">${this.value}</span>`);
                return `
            <li>
              <span class="name">${cityName}, ${stateName}</span>
              <span class="population">${numberWithCommas(place.population)}</span>
            </li>
          `;
            })
            .join('');
        suggestions.innerHTML = html;
    }

07 - Array Cardio Day 2

Demo

  • some

    檢查陣列中元素,有一元素符合條件則回傳 true

    const isAdult = people.some((person) => new Date().getFullYear() - person.year >= 19);
  • every

    檢查陣列中元素,全部元素符合條件則回傳 true

    const allAdults = people.every((person) => new Date().getFullYear() - person.year >= 19);
  • find

    回傳陣列中第一個符合條件的元素

    const comment = comments.find((comment) => comment.id === 823423);
  • findIndex

    回傳陣列中第一個符合條件的元素索引

    const index = comments.findIndex((comment) => comment.id === 823423);
    
    // comments.splice(index, 1);
    
    const newComments = [...comments.slice(0, index), ...comments.slice(index + 1)];
  • splice vs slice

    • array.splice(start[, deleteCount[, item1[, item2[, ...]]]])
    • array.slice([begin[, end]])
    • slice 組成新陣列,則可用
    const newComments = [...comments.slice(0, index), ...comments.slice(index + 1)];

08 - Fun with HTML5 Canvas

Demo

  • JS 取得現在視窗大小

    • window.innerWidth , window.innerHeight
  • Canvas 設置

    • 大小設置
    const canvas = document.querySelector('#draw');
    const ctx = canvas.getContext('2d');
    
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    // Start drawing
    ctx.beginPath();
    // start from
    ctx.moveTo(lastX, lastY);
    // go to
    ctx.lineTo(e.offsetX, e.offsetY);
    // Draw
    ctx.stroke();
  • Array deconstruct 技巧

    • [X, Y] = [newX, newY];
  • hsl 顏色

    • hsl(hue, saturation, lightness)
    • hue = 0 ~ 360
    • saturation, lightness = 0 ~ 100%

09 - Dev Tools Domination

Demo

  • Chrome dev tools

    • 在元素上按右鍵 => break on => attribute modification
  • console.log()

    • %s => 加入字串
    console.log('Hello I am a %s string!', '💩');
    • %c => 加入 CSS
    console.log('%c I am some great text', 'font-size:50px; background:red; text-shadow: 10px 10px 0 blue');
  • console 系列

    • console.warn()
    • console.error()
    • console.info()
    • console.assert(statement, 'Word that show when statement == false')
    console.assert(p.classList.contains('ouch'), 'That is wrong!');
    • console.clear()
    • console.dir()
    console.log(p);
    console.dir(p);
    • console.group() / console.groupCollapsed() + console.log() *n + console.groupEnd()
    dogs.forEach((dog) => {
        console.groupCollapsed(`${dog.name}`);
        console.log(`This is ${dog.name}`);
        console.log(`${dog.name} is ${dog.age} years old`);
        console.log(`${dog.name} is ${dog.age * 7} dog years old`);
        console.groupEnd(`${dog.name}`);
    });
    • console.count()
    • console.time() + console.timeEnd()
    console.time('fetching data');
    fetch('https://api.github.com/users/wesbos')
        .then((data) => data.json())
        .then((data) => {
            console.timeEnd('fetching data');
            console.log(data);
        });
    • console.table()

10 - Hold Shift and Check Checkboxes

Demo

  • 偵測使用者用 shift 鍵做選取

    • e.shiftKey
  • <input>[type="checkbox"]

    input:checked+指定元素 去操作打勾後的 CSS 變化

    input:checked+p {
        background: #F9F9F9;
        text-decoration: line-through;
    }
  • 用 !isBoolean 操作 toggle

    if (node === lastChecked || node === this) {
        isInBetween = !isInBetween;
    }

11 - Custom Video Player

Demo

  • <video> html tag

    • 自動播放:autoplay
  • <video> node 操作

    • 影片是否暫停:video.paused
    • 影片目前時間:video.currentTime
    • 影片總共時間:video.duration
    • 播放影片:video.play()
    • 暫停影片:video.pause()
    • 監聽事件:video.addEventListener('play'/'pause'/'timeupdate');
  • querySelector 可以將 node 當作目標選取內元素

    const player = document.querySelector('.player');
    const video = player.querySelector('.viewer');
  • querySelector 可以將 attribute 當作 selector

    const skipButtons = player.querySelectorAll('[data-skip]');
  • 將物件 method 當作變數執行

    const method = video.paused ? 'play' : 'pause';
    video[method]();
  • 改變 node 內文字正統方法

    toggle.textContent = icon;
  • <input> range 改變屬性的簡潔寫法

    HTML

    <input type="range" name="volume" class="player__slider" min="0" max="1" step="0.05" value="1">
    <input type="range" name="playbackRate" class="player__slider" min="0.5" max="2" step="0.1" value="1">

    JS

    function handleRangeUpdate() {
        video[this.name] = this.value;
    }
  • flex 調整比例做進度條

    • 外層元素
      • display: flex
      • flex: >0
      • flex-basis: 100%
    • 內層元素
      • flex: 0
      • flex-basis: progress percentage
  • JS 選取元素長度

    • e.offsetX
    • node.offsetWidth
  • if statement 則執行一個 function 的簡潔寫法

    (e) => mousedown && scrub(e);

12 - Key Sequence Detection

Demo

  • 監聽按鍵事件
    • addEventListener('keyup', (e)=>{console.log(e.key)})
  • .splice()
    • array.splice(start[, deleteCount[, item1[, item2[, ...]]]])
    • start 若為負,則從最後一個元素往前數(-1 開始)

13 - Slide in on Scroll

Demo

  • debounce

    • Scroll 事件觸發太頻繁,需要限制單位時間內觸發頻率
    • lodash 中有現成的
  • 計算 Scroll 高度 scrollY + innerHeight

    • window.scrollY:視窗上緣離網頁上緣的距離
    • window.innerHeight:視窗目前的高度
  • 計算網頁到元素最上緣的距離

    const slideInAt = window.scrollY + window.innerHeight - sliderImage.height;
  • 計算網頁到元素最下緣的距離

    const imageBottom = sliderImage.offsetTop + sliderImage.height;
  • node.offsetTop

    • 計算元素上緣離網頁上緣的距離

14 - JavaScript References VS Copying

Demo

  • copy 一個陣列的四種方法

    const team2 = players.slice();
    
    const team3 = [].concat(players);
    
    const team4 = [...players];
    
    const team5 = Array.from(players);
  • copt 一個物件的三種方法

    const cap2 = Object.assign({}, person, { number: 99, age: 12 });
    
    const cap3 = { ...person };
    
    const dev2 = JSON.parse(JSON.stringify(wes));
  • Note

    • 只有 JSON.parse(JSON.stringify(wes)) 這個方法會遍歷每一層的物件,其他方法都只能 copy 一層

15 - LocalStorage

Demo

  • <form> tag

    • default 在 submit 事件發生後會重新整理頁面
    • form.addEventListener('submit') 會吃到 enterclick 等等
    • 存取 form tag 裡的 input
    const text = this.querySelector('[name=item]').value;
    • this.reset() 可以把 input 清空
  • <label> tag

    • checkbox 實作:連結 id => for
    <input type="checkbox" data-index=${i} id="item${i}"/>
    <label for="item${i}">${plate.text}</label>
    • CSS:用 input:checked + label:before 控制變化
    .plates input {
        display: none;
    }
    
    .plates input + label:before {
        content: '⬜️';
        margin-right: 10px;
    }
    
    .plates input:checked + label:before {
        content: '🌮';
    }
  • Local Storage

    • Dev tools:Application => Storage => Local Storage
    • API
    localStorage.setItems('key', 'value');
    localStorage.getItem('key');
    localStorage.remove('key');
    • value 會被強制 toString(),所以設置前要先把 object 轉成 string
    localStorage.setItem('items', JSON.stringify(items));
  • Delegation

    • 把監聽事件放在外層元素,讓內層新增的元素也可以被監聽
    • e.target.matches('yourTarget') 指定
  • array.map()

    • map 吃得第二個參數為 index

16 - Mouse Move Shadow

Demo

  • 可編輯文字的 tag attribute

    • contenteditable
  • destructor

    const { offsetWidth: width, offsetHeight: height } = hero;
    let { offsetX: x, offsetY: y } = e;
  • JS 中的四捨五入

    • math.round()
  • CSS textShadow :可以同時給多個值

    ${xShadow}px ${yShadow}px ${blur}px ${color}

17 - Sort Without Articles

Demo

  • RegExp

    • 對照前綴有無 a the then

      return bandName.replace(/^(a |the |an )/i, '').trim();
    • 注意對照空格 (a |the )(a|the) 還有 (a| the |) 結果不同

18 - Adding Up Times with Reduce

Demo

  • 轉換陣列元素型態到數值

    array.map(parseFloat);
  • 轉換 NodeList 到 Array

    // Array.from
    const timeNodes = Array.from(document.querySelectorAll('[data]'));
    
    // Spread
    const timeNodes = [...document.querySelectorAll('[data]')];
  • 無條件捨去

    • Math.floor()

19 - Webcam Fun

Demo steps:

cd 19\ -\ Webcam\ Fun/

npm install

npm run start

  • 取得 Webcam 權限

    • 需要開在安全的server / localhost
    • 可以用簡單的 package.json
    {
      "name": "gum",
      "version": "1.0.0",
      "description": "",
      "main": "scripts.js",
      "scripts": {
        "start": "browser-sync start --server --files \"*.css, *.html, *.js\""
      },
      "author": "",
      "license": "ISC",
      "devDependencies": {
        "browser-sync": "^2.12.5 <2.23.2"
      }
    }
  • JS 中取得 Webcam 影像

    • navigator.mediaDevices.getUserMedia 會得到一個 Promise 物件
    • video.src = window.URL.createObjectURL(localMediaStream); 拿到影像
    navigator.mediaDevices
        .getUserMedia({ video: true, audio: false })
        .then((localMediaStream) => {
            console.log(localMediaStream);
            video.src = window.URL.createObjectURL(localMediaStream);
            video.play();
        })
        .catch((err) => {
            console.error(`OH NO!!!`, err);
        });
  • 拿到 video 的實際寬高

    • video.videoHieght , video.videoWidth
  • 用 canvas 輸出 Webcame Stream

    return setInterval(() => {
        ctx.drawImage(video, 0, 0, width, height);
        // take the pixels out
        let pixels = ctx.getImageData(0, 0, width, height);
    }, 16);
  • 監聽 video 準備好的事件

    video.addEventListener('canplay', paintToCanvas);
  • 把 canvas 資料取出,轉化成 Base64

    const data = canvas.toDataURL('image/jpeg');
    const link = document.createElement('a');
    link.href = data;
  • Base64 資料

    • 基本上圖片轉換成一長串的字串,可以直接代表圖片,因此在網頁中把圖片打開,其實只是讓瀏覽器解析那一長串的字串代表什麼樣的圖片
  • 設定可下載的連結跟預覽

    link.setAttribute('download', 'handsome');
    link.innerHTML = <img src="${data}" alt="Handsome Man" />;
  • 取得 canvas 中影像的 pixel

    let pixels = ctx.getImageData(0, 0, width, height);
  • 更改 pixel 產生 filter

    • pixel.data 為一個陣列,每個影像上的點都由四個連續的數值決定,從 pixel[0]pixel[3] 分別代表 rgba
    function redEffect(pixels) {
        for (let i = 0; i < pixels.data.length; i += 4) {
            pixels.data[i + 0] = pixels.data[i + 0] + 200; // RED
            pixels.data[i + 1] = pixels.data[i + 1] - 50; // GREEN
            pixels.data[i + 2] = pixels.data[i + 2] * 0.5; // Blue
        }
        return pixels;
    }
    • 製造出 rgba 分離
    function rgbSplit(pixels) {
        for (let i = 0; i < pixels.data.length; i += 4) {
            pixels.data[i - 150] = pixels.data[i + 0]; // RED
            pixels.data[i + 500] = pixels.data[i + 1]; // GREEN
            pixels.data[i - 550] = pixels.data[i + 2]; // Blue
        }
        return pixels;
    }
    • 製造殘影
    ctx.globalAlpha = 0.1;
  • 把更改後的 pixel 放回 canvas

    ctx.putImageData(pixels, 0, 0);
  • prepend child 的方法

    outer.insertBefore(inner, outer.firsChild);
  • debugger

    • 可以直接在 JS 中設置暫停點

20 - Speech Detection

Demo steps:

cd 20\ -\ Speech\ Detection/

npm install

npm run start

  • 瀏覽器中的 Speech Recognition

    • window.SpeechRecognition or window.webkitSpeechRecognition
  • 基本設置

    const recognition = new SpeechRecognition();
    // ? 即時辨識 : 停頓辨識
    recognition.interimResults = true;
    recognition.lang = 'en-US';
    
    recognition.start();
  • 監聽 recognition 事件

    • recognition.addEventListener('result')

    • recognition.addEventListener('end')

  • result 回傳事件

    • e.results => 回傳一個 SpeechRecognitionResultList
    • e.results[0].isFinal => 回傳布林值判斷是否有斷句
    • e.results[0].transript => 回傳辨識結果

21 - Geolocation

Demo steps:

cd 21\ -\ Geolocation/

npm install

npm run start

  • 模擬器
    • Xcode => Open Dev Tool => Simulator
    • Xcode 上可以打開 Dev Tool 的 console
    • Simulator => Debug => Location 可以模擬通勤方式
  • 持續檢視位置
    • navigator.geolocation.watchPosition(data)
  • 移動速度
    • data.coords.speed
  • 移動方位
    • data.coords.heading

22 - Follow Along Link Highlighter

Demo

  • Navigator transition 效果
  • highlight 隨滑鼠移動
    • 用一個 block 元素,在 link 跟 link 之間 hover 時移動
  • 得到元素位置與大小
    • this.getBoundingClientRect()
  • 讓元素隨 link 位置移動
    • translate 的話,要加上 scroll 的數值

23 - Speech Synthesis

Demo

  • 把 text 轉換成 voice

    • speechSynthesis 負責接收文字轉換發出聲音
    • new SpeechSynthesisUtterance() 負責設定文字素材
  • 監聽 speechSynthesis 事件

    • speechSynthesis.addEventListener('voiceschanged', populateVoices);
  • speechSynthesis method

    • .getVoice() 得到發出聲音的人 .name 和語言縮寫 .lang
    • .speak() 發出聲音
    • .cancel() 終止發聲
  • 從 dropdown 選單找對應 property

    msg.voice = voices.find((voice) => voice.name === this.value);
  • 在 addEventListener 中的 callback 加入參數的方法

    • bind
    addEventListener('event', toggle.bind(null, this));
    • arrow function
    addEventListener('event', () => toggle(false));
  • 重複利用同個 function 做 speak 跟 stop(類似多型概念)

    • 用 default parameter,對特定的再傳另外的 parameter
    function togglePlay(startOver = true) {
        speechSynthesis.cancel();
        if (startOver) {
            speechSynthesis.speak(msg);
        }
    }
    
    speakButton.addEventListener('click', togglePlay);
    stopButton.addEventListener('click', () => togglePlay(false));

24 - Sticky Nav

Demo

  • position fixed
    • 元素不佔空間,如果為後加的則網頁元素會變動位置
    • 可用 padding-top = offsetHeight抵銷
  • 偵測 Nav 跟 網頁最高處的距離
    • offsetTop

25 - Event Capture, Propagation, Bubbling and Once

Demo

  • Event bubbling
    • Caputure down, bubble up
  • 只觸發一個
    • e.propagation()
  • addEventListener 的參數
    • capture: true 捕獲階段觸發
    • once: ture 只觸發一次後就 unbind 事件

26 - Stripe Follow Along Nav

Demo

  • display: none & opacity: 0出現的效果

    • 先轉換成 display: block,設 setTimeout 讓 opacity: 1 在 150ms 後在變換
    • 要先有 display,transition-duration 才會有效果
    • 這樣可能會導致在還沒有過 150ms 就 mouseout 時出現 bug,所以要在確定變完第一個時在便第二個
    setTimeout(() => this.classList.contains('trigger-enter') && this.classList.add('trigger-enter-active'), 150);
  • 指定 hover 到的元素下的元素

    const dropdown = this.querySelector('.dropdown');
    const cords = dropdown.getBoundingClientRect();

27 - Click and Drag

Demo

  • Drag and scroll 效果,需要監聽的事件

    • mousedown , mouseleave , mouseup , mousemove
  • Click 在外層元素裡的位置

    • e.pageX 在整個網頁的位置
    • - slider.offsetLeft 扣掉外層元素的位置
  • console.log debug 小技巧

    • 印出 { variables } 可以同時知道印出的是哪個變數
  • 製造 scroll 效果

    // mousedown
    startX = e.pageX - slider.offsetLeft;
    scrollLeft = slider.scrollLeft;
    
    // mousemove
    const x = e.pageX - slider.offsetLeft;
    const walk = (x - startX) * 3;
    slider.scrollLeft = scrollLeft - walk;

28 - Video Speed Controller

Demo

  • 在外層元素裡的位置高度

    • e.pageY - this.offsetTop
  • 元素 height 用 percent 衡量

    const height = Math.round(percent * 100) + '%';
  • 小數點後兩位

    • number.toFixed(2)
  • video 播放速度

    • video.playbackRate

29 - Countdown Timer

Demo

  • setInterval 累加顯示時間的問題

    • 在 Browser 不一定準
    • 在 iOS,scroll 發生時會 pause setInterval
  • Date.now()

    • 會回傳一個以毫秒為單位的時間
    • 可以把得到的數值放回 new Date( Date.now() ) 中得到 Date 物件
  • 倒數計時

    const now = Date.now();
    const then = now + seconds * 1000;
    setInterval(() => {
        const secLeft = Math.round((then - Date.now()) / 1000);
    }, 1000);
  • 終止 setInterval

    • setInterval 指派給一個變數 var1
    • clearInterval(var1)
  • setInterval 不會在第零秒時觸發,故開始時間要用額外 operation

  • 網頁的標題 tab

    • document.title
  • 用 name attribute 取代 querySelector

    const customForm = document.customForm;
  • Form & Input

    • submit 監聽
    • e.preventDefault() 避免重新整理
    • this.reset() 清空 input

30 - Whack A Mole

Demo

  • Random(min, max)

    return Math.round(Math.random() * (max - min) + min);
  • 避免 fake mouse click

    • e.isTrusted = true

javascript30's People

Contributors

hcwxd avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.