物件導向 彙整 | Creative Coding TW - 互動程式創作台灣站 https://creativecoding.in/tag/物件導向/ 蒐集互動設計案例、教學與業界資源,幫助你一起進入互動程式創作的產業 Mon, 30 May 2022 14:33:51 +0000 zh-TW hourly 1 https://wordpress.org/?v=6.2.2 https://creativecoding.in/wp-content/uploads/2022/03/cropped-cct-logo-icon-2-32x32.png 物件導向 彙整 | Creative Coding TW - 互動程式創作台灣站 https://creativecoding.in/tag/物件導向/ 32 32 【互動網頁程式教學】活用GUI Object與繼承概念,完成Canvas物件導向的滑鼠拖曳互動 https://creativecoding.in/2022/06/16/gui-object-canvas/ Thu, 16 Jun 2022 02:19:00 +0000 https://creativecoding.in/?p=2879 利用GUI Object的概念,快速畫出多個物件,利用canvas物件導向概念加上事件偵測,讓滑鼠位置與物件互動,達成亮度的提示以及拖曳物件。

這篇文章 【互動網頁程式教學】活用GUI Object與繼承概念,完成Canvas物件導向的滑鼠拖曳互動 最早出現於 Creative Coding TW - 互動程式創作台灣站

]]>
很多的讀者經常使用像是canvas這樣的函式庫,東西已經包裝成物件,可以輕鬆的拖曳、偵測點擊。這次的老闆週四寫程式,要來教大家在不使用函示庫的情況下,直接使用純繪圖的canvas生成物件,並偵測事件,來用滑鼠點選跟拖曳物件。

Canvas 物件導向與繼承,來做個土炮架構控制元件吧!(上)成品圖
Canvas 物件導向與繼承,來做個土炮架構控制元件吧!(上)成品圖

目標

這篇文章將會讓你學到:

  1. 向量的基礎知識
  2. 把純繪圖的canvas包成物件的架構
  3. 利用物件導向完成元件與滑鼠的基礎互動

架構

此次影片要實作圖形使用者介面(Graphical User Interface,本篇後以GUI稱之)作為小畫家的操作介面。GUI是採用圖形方式顯示的使用者介面,讓使用者可以使用滑鼠或相關設備操縱螢幕上的圖標或菜單選項,跟早期的電腦使用命令列介面相比,讓使用者在視覺上更容易接受。

實作GUI前,可以先了解一下物件設計的架構:

  1. 成品中的每個方塊都是一個GUI object
  2. 而所有的方塊可以形成一個GUI group
  3. 最後再交由GUI scene 畫出整個場景
GUI結構示意圖
GUI結構示意圖
GUI結構範例
GUI結構範例

了解向量

向量加法示意圖
向量加法示意圖

在畫布的操作中,位置是很重要的一環,位置通常由座標(通常是x,y)構成,物件的起始位置與終點位置,可以看作為「座標的變化量」,而「向量」正是可以輕鬆的表示出座標的變化。(小觀念:向量的定義為 方向的變化量

在程式碼中使用「向量」概念

先來做一個向右跑的小方塊作為使用向量的範例。我們把 HTML 的 Preprocessor 設為 Pug 再把 CSS 設為 Sass,在 HTML 中先畫一個 canvas#mycanvas。

使用「座標」畫出白色方塊物件並讓物件向右移動:

// JS setting
var ww,wh
var canvas = document.getElementById("mycanvas")
var ctx = canvas.getContext("2d")
function init(){
  ww = window.innerWidth
  wh = window.innerHeight
  canvas.width = ww
  canvas.height = wh
}
init()
window.addEventListener("resize",init)
 
//使用「座標」定義物件
var obj = {
  p:{
    x: 0,
    y:0
  },
  size:{
    x:100,
    y:100
  },
  v:{
    x:5,
    y:0
  }
}
function draw(){
  ctx.fillStyle="black" //把上一個畫面蓋掉
  ctx.fillRect(0,0,ww,wh) //把上一個畫面蓋掉
  ctx.fillStyle="white"  
  ctx.fillRect(obj.p.x,obj.p.y,obj.size.x,obj.size.y)
}
setInterval(draw,30)
 
function update(){
  obj.p.x += obj.v.x
  obj.p.y += obj.v.y
}
 
setInterval(update,30)

可以從這一段程式碼中,看到定義物件的位置時,需要個別設置x與y的變量,在 update 物件位置時,也需要個別對x與y做處理。

使用「向量」畫出物件及物件移動:

// 定義向量class,並加入向量的加(add)減(sub)乘(mul)運算
class Vec2{
  constructor(x,y){
    this.x=x
    this.y=y
  }
  add(v){
    return new Vec2(this.x+v.x,this.y+v.y)
  }
  mul(s){
    return new Vec2(this.x*s,this.y*s)
  }
  sub(v){
    return this.add(v.mul(-1))
  }
}
 
var obj = {
  p: new Vec2(0,0), // new 一個向量物件
  size:new Vec2(100,100), // new 一個向量物件
  v: new Vec2(5,0) // new 一個向量物件
}
function draw(){
  ctx.fillStyle="black"
  ctx.fillRect(0,0,ww,wh)
  ctx.fillStyle="white"  
  ctx.fillRect(obj.p.x,obj.p.y,obj.size.x,obj.size.y)
}
setInterval(draw,30)
 
function update(){
  obj.p = obj.p.add(obj.v) //使用向量概念中的「相加」
}

setInterval(update,30)

先實作出一個向量類 Vec2,後續使用 new Vec2 就可以使用向量。在後續需要大量生成物件時,可以比座標更容易生成大量物件。

小結:使用向量物件讓程式碼更簡潔,也讓位置設置變得更容易了。

實作

此次實作會用到老師預先製作好了template,內容包含了向量類 Vec2、畫布設置以及一些滑鼠的事件及記錄,可以參考這裏,需要的同學可以fork一份回自己的codePen再往下繼續做呦!

製作物件

一開始需要建立一個GUIObject 類,方便後續快速製造出大量的GUI object。另外再預先定義一個Scene類,並且在裡面增加 addChild(),把所有的GUIObject可以放在children 中,方便畫出。

class  GUIObject{
  constructor(args){
    let def={
      p: new Vec2(0,0),
      size: new Vec2(0,0)
    }
    Object.assign(def,args)
    Object.assign(this,def)
  }
  draw(){
    ctx.fillStyle="white"
    ctx.fillRect(this.p.x,this.p.y,this.size.x,this.size.y)
  }
}
 
class Scene{
  constructor(args){
    let def={
      children: []
    }
    Object.assign(def,args)
    Object.assign(this,def)
  }
  addChild(obj){
    this.children.push(obj)
  }
  draw(){
    this.children.forEach(obj=>{
      obj.draw()
    })
  }
}

接著可以利用剛剛定義好的GUIObject直接畫出一個長方形。

var rect = new GUIObject({ 
  p: new Vec2(30,30),
  size: new Vec2(100,30)
})
 
function draw(){
  ...
  rect.draw()
  ...
}
利用物件導向畫出一個方塊
利用物件導向畫出一個方塊

函式多載

現在要來做一點程式碼的優化。

函式多載是讓一個同名函式帶入的參數可以有不同類型跟不同數量。在函式內做類型判別跟數量判別,可以讓後續在呼叫函式的時候更容易。

現在scene的addChild只能放入一個物件,並且無法判斷進入的物件是不是scene期待的GUIObject。因此要在這邊修改addChild,讓user給什麼都可用,無論是給一個GUIObject、給多個GUIObject或給一個array都可以運行。

addChild(){
  if (arguments.length==1){ // 如果input的arguments只有一個
    if(arguments[0] instanceof GUIObject){ // 如果input的剛剛好是GUIObject
      this.children.push(arguments[0])
    }
    if(arguments[0] instanceof Array){ // 如果input的是array,這邊暫時不檢查裡面是否皆為GUI object
      this.children = this.children.concat(arguments[0])
    }
  }else{
    for(var i=0;i<arguments.length;i++){ // 如果input了很多個object
      this.children.push(arguments[i])
    }
  }
}

addChild得到的input為arguments, 可以看到程式碼中對arguments進行判斷與操作。我們在這邊繪製兩個長方形,讓Scene蒐集GUIObject後一起畫出。(後續會使用這個方式)

var scene = new Scene()
function init(){
  let rect = new GUIObject({
    p: new Vec2(30,30),
    size: new Vec2(100,30)
  })
  let rect2 = new GUIObject({
    p: new Vec2(130,30),
    size: new Vec2(200,200)
  })
  scene.addChild(rect,rect2) // 防呆裝置已啟動
}
function draw(){
  scene.draw()
}
利用修改後的function生成多個方塊
利用修改後的function生成多個方塊

物件與滑鼠互動

完成物件後,我們最後要加入滑鼠與物件的幾種互動。

(1) 滑鼠靠近方塊,改變顏色

這個小動態的目的是要讓user知道滑鼠有沒有放在物件上,先讓物件亮度降低,當物件與滑鼠位置重疊,便讓物件亮度上升:

a. 新增一個 isHovering 參數,如果是true就調整物件亮度

class GUIObject{ 
  constructor(args){
    let def={
      ...,
      isHovering: false // 新增一個 isHovering 參數,預設為false
    }
   ...
  }
  draw(){
    ctx.fillStyle="rgba(255,255,255,0.4)"
    if (this.isHovering){
      ctx.fillStyle="rgba(255,255,255,1)"
    }
    ...
  }
}

b. 要偵測滑鼠位置(在Scene 類加入事件偵測)

class Scene{ 
  constructor(args){
    let def={
      ...,
      el: null // 要知道是哪個document, 在new的時候指定
    }
    ...
    this.init()
  }
  init(){
    // 事件偵測
    this.el.addEventListener("mousemove",(evt)=>{
      let mousePos = new Vec2(evt.x,evt.y) // 拿滑鼠位置
      // 處理滑鼠移動
      this.children.forEach(obj=>{
        obj.handleMouseMove(mousePos) //傳入滑鼠位置
      })
    })
  }
}
 
// 在new的時候指定document
var scene = new Scene({
  el: document.querySelector("canvas")
})

c. 加入 handleMouseMove 來改變 isHovering 參數的值

class GUIObject{
  ...
  handleMouseMove(pos){
    let point1 = this.p,
        point2 = this.p.add(this.size)
    // 判斷滑鼠是否在物件範圍內
    if (pos.x>point1.x && pos.x < point2.x &&
      pos.y>point1.y && pos.y < point2.y){
      this.isHovering = true
    }else{
      this.isHovering = false
    }
  }
}
滑鼠靠近方塊,改變方塊顏色並改變鼠標圖示
滑鼠靠近方塊,改變方塊顏色並改變鼠標圖示

(2) 用滑鼠拖移方塊

當滑鼠位置與物體重疊時,點擊滑鼠右鍵,可以拖移物件:

a. 新增 isDraggable 參數來決定物件是否可以被拖移

class GUIObject{
  constructor(args){
    let def={
      ...
      isDraggable: false
    }
    ...
  }
 
// 在new GUIObject時要記得把 isDraggable設成true
function init(){
  let rect = new GUIObject({
    p: new Vec2(30,30),
    size: new Vec2(100,30),
    isDraggable: true
  })
}

b. 新增 InRange function 來判斷滑鼠位置是否在物件內 (可以重複使用)

class GUIObject{
  ...
  inRange(pos){
    let point1 = this.p,
        point2 = this.p.add(this.size)
    return pos.x>point1.x && pos.x < point2.x &&
           pos.y > point1.y && pos.y < point2.y
  }
  ...
}

c. 新增 dragging 參數來判斷物件是否正在被拖移中

class GUIObject{
  constructor(args){
    let def={
      ...
      isDraggable: false,
      dragging: false
    }
   ...
  }
}

d. 新增 handleMouseDown 及 handleMouseUp 來處理滑鼠按鍵的事件處理

class GUIObject{
  ...
  handleMouseMove(pos){
  if (this.inRange(pos) ){
    this.isHovering = true
  }else{
    this.isHovering = false
  }
  if (this.dragging){
    this.p = this.p.add(pos.sub(this.lastPos))
    this.lastPos = pos
  }
}
 
handleMouseDown(pos){
  if (this.inRange(pos)){
    this.lastPos = pos
    if (this.isDraggable){
      this.dragging = true
    }
  }
}
handleMouseUp(){
  this.lastPos = null
  this.dragging = false
}

e. 事件偵測加入滑鼠按鍵按下與鬆開的偵測

class Scene{
  ...
  init(){
    ...
    // 按下滑鼠按鍵
    this.el.addEventListener("mousedown",(evt)=>{
      let mousePos = new Vec2(evt.x,evt.y)
      this.children.forEach(obj=>{
        obj.handleMouseDown(mousePos)
      })
    })
    // 放開滑鼠按鍵
    this.el.addEventListener("mouseup",(evt)=>{
      let mousePos = new Vec2(evt.x,evt.y)
      this.children.forEach(obj=>{
        obj.handleMouseUp(mousePos)
      })
    })
 ...

f. 改變鼠標,當鼠標指到物件時,鼠標會從箭頭變成👉🏻

class Scene{
  constructor(args){
    let def={
      …
      flag: false
    }
  }
  ...
  update(){
    if(this.flag){
      this.el.style.cursor="pointer"
    }else{
      this.el.style.cursor="initial"
    }
  }
  init(){
    let flag = false
    this.el.addEventListener("mousemove",(evt)=>{
      this.flag = false
      let mousePos = new Vec2(evt.x,evt.y)
      this.children.forEach(obj=>{
        if(obj.handleMouseMove(mousePos)){
          this.flag = true
        }
      })
    })
  }
  ...
}
// 讓scene update起來
function update(){
  time++
  scene.update()
}
滑鼠拖移方塊位置成果圖
滑鼠拖移方塊位置成果圖

完成滑鼠與物件的基礎互動啦!

結語

以上就是老闆利用Canvas做滑鼠控制物件的網頁基礎互動,這次在前面講解概念的部分花了較多時間,來不及完成小畫家,希望對於剛開始接觸 Canvas 的你有一些幫助。

再次快速總結步驟:

  1. 利用GUI Object的概念,快速畫出多個物件
  2. 加上事件偵測,讓滑鼠位置與物件互動,達成亮度的提示
  3. 加上滑鼠按鍵的事件偵測,讓滑鼠拖移物件

看著框框跟隨著滑鼠的移動,真的很有成就感啊!

老闆的工商時間

想了解更多如何寫出漂亮清晰的網頁嗎?老闆在 Hahow 的教學課程 動畫互動網頁程式入門(HTML/CSS/JS) 用平易近人的語言,用簡單的方式帶你作出不簡單的網頁。已經有網頁程式基礎了嗎?進階課程 動畫互動網頁特效入門(JS/CANVAS) 能讓你紮實掌握 JavaScript 程式與動畫基礎以及進階互動,整合應用掌控資料與顯示的Vue.js前端框架,完成具有設計感的互動網站。

此篇直播筆記由幫手 Y-Y-H 協助整理

墨雨設計banner

這篇文章 【互動網頁程式教學】活用GUI Object與繼承概念,完成Canvas物件導向的滑鼠拖曳互動 最早出現於 Creative Coding TW - 互動程式創作台灣站

]]>
基礎JS物件導向教學(直播筆記) https://creativecoding.in/2021/03/31/js%e7%89%a9%e4%bb%b6%e5%b0%8e%e5%90%91%e9%9a%a8%e6%84%8f%e5%af%ab%e7%a8%8b%e5%bc%8f%e7%9b%b4%e6%92%ad%e7%ad%86%e8%a8%98/ Wed, 31 Mar 2021 10:35:00 +0000 https://creativecoding.in/?p=526 這篇文章老闆想跟大家分享物件導向,以及如何使用 js 結合物件導向概念包裝東西,創造並管理物件。 本文翻自 0212 隨意寫程式直播 / 物件導向,若是對文章內容有疑問,或是想要跟著影片一起做,都可以…

這篇文章 基礎JS物件導向教學(直播筆記) 最早出現於 Creative Coding TW - 互動程式創作台灣站

]]>
這篇文章老闆想跟大家分享物件導向,以及如何使用 js 結合物件導向概念包裝東西,創造並管理物件。

本文翻自 0212 隨意寫程式直播 / 物件導向,若是對文章內容有疑問,或是想要跟著影片一起做,都可以點入觀看影片詳細內容。

工商時間:老闆亂入在這打個小廣告 – 動畫互動網頁特效入門(JS/CANVAS)。網頁技術博大精深,學也學不完,老闆很開心不少同學在上過老師的課程後,成功加入 coder 的一員。 其他平台在對於 js 的課程教學內容上,已經很完善。但這門課不一樣的地方是,老闆會在課程中穿插不同的範例(例如摩斯密碼…等),有興趣的也可以支持一下。

目標

  1. 物件導向是什麼
  2. 使用 js 結合物件導向概念包裝東西

為什麼需要物件導向?

這邊我們舉個飛機射擊打怪獸遊戲作為例子。在這個遊戲中,操作者按下射擊會射出子彈,按鍵移動飛機…等功能,在監聽到前述事件後,需要不斷地增加子彈,或是針對飛機進行畫面位置改變,若只是規則簡易的小遊戲,這些都還能硬寫完成。但是當遊戲複雜度增加、要控制的物件增加時,就會讓製作過程非常痛苦。

再舉一個例子,假設今天 人物A 要將 蘋果 交給 人物B 的過程,若是不看畫面,在程式碼內應該要看到三個物件(人物A 、人物B、蘋果),程式碼就會像下面這樣:

A.給(B, 蘋果)

我們把非常繁雜的物件、屬性包成一個抽象的概念,讓他們之間去做互動,管理物件的方式,讓大家在寫程式的時候,不會被底層的內容給干擾。需要使用物件導向的原因,就是因為我們需要一個抽象的介面來處理這些事情。希望能夠透過物件導向,將程式碼簡潔,也不會讓遊戲分數或是各種邏輯條件的程式碼四散各處。

接下來我們來一起寫一些程式,加深對物件導向的理解。

邁向物件導向

要什麼就宣告什麼

我們先來建立一個會打招呼的人,他的名字叫Frank:

var person_name = 'Frank'
var personSpeak = function (name) {
  console.log('Hello, ' + name)
}
personSpeak(person_name) // Hello, Frank

這樣寫會發現一個狀況,人名和他的動作(Speak)是分開的,這樣對於管理並不友善,所以接下來我們嘗試將人名與說話的方法統一管理。

物件屬性統一管理

接著我們嘗試結合物件,將跟人有相關的屬性(名字、性別、年紀…等)包成物件。這種方式讓函式可以吃到人的所有屬性,也可以針對此來做更多的變化,我們試著把程式碼改動成:

var person = {
  name: 'Frank',
  gender: 'Male'
}
function personSpeak (person) {
  console.log('Hello, ' + person.name, person.gender)
}
personSpeak(person) // Hello, Frank, Male

將 function 也放進物件中

但是當程式越來越大,人有太多的屬性,每次呼叫 function 都要傳人這個參數進去,會覺得有點麻煩。這時候,我們開始思考,是不是要連名字也一起放進來,就不用在呼叫 function 的時候,還要傳人的屬性進去,所以我們把程式碼改動成:

var person = {
  name: 'Frank',
  gender: 'Male',
  speak: function () {
    console.log('Hi, I\'m ' + this.name + '!')
  }
}
person.speak() // Hi, I'm Frank!

這個概念可以延伸到我們在寫遊戲,要讓遊戲物件棋子往前,不需要呼叫往前並傳入棋子這個參數,而是針對這個棋子呼叫往前的 function。

類別定義、函數產生器

當只要產生一個人的時候,我們宣告物件很容易,但是當今天要產生五個、十個、甚至一百個的時候,我們不可能打一百個 var person98… var person99… var person100 吧?所以接下來將這種宣告方式改寫成物件產生器。我們將這種物件產生器稱為「類別定義(模板)」。現在不管要幾個人,我們就可以使用這種方式產出無限多人了!

🔔小叮嚀:類別為抽象概念,程式語言的習慣上也會將類別的首字大寫

var Person = function (name, gender) {
  this.name = name
  this.gender = gender
  this.speak = function () {
    console.log('Hi, I\'m ' + this.name + '!')
  }
}
var person1 = new Person ('Frank', 'Male')
var person2 = new Person ('Mick', 'Female')
person1.speak() // Hi, I'm Frank!
person2.speak() // Hi, I'm Mick!

抽出共同方法

現在我們使用 chrome 的開發者工具,檢查 person1, person2 的結構會發現。產生器所產出的每個物件,包進去的函式都是一個新的 function ,並不是共用的。

person1.speak = function () {
  console.log('Hello, I\'m ' + this.name + '!')
}
person1.speak() // Hello, I'm Frank!
person2.speak() // Hi, I'm Mick!

這時狀況來了,假設今天我們要改變某一個人說話這個函式的內容,就必須一個一個去修改。這樣的操作顯得有點不人性化。我們希望能夠在修改函式的時候,只需修改一次。所以我們可以試著將共同的函式抽出,只要是抽象定義共用的,我們就將它拉出來,而不是再複製一份。

我們針對人這個類別,將共同的函式抽出,改使用 prototype(原型,不會變動的,有點像是人的根源的概念)。

var Person = function (name, gender) {
  this.name = name
  this.gender = gender
}
// 將共同方法抽出
Person.prototype.speak = function () {
  console.log('Hi, I\'m ' + this.name + '!')
}
var person1 = new Person ('Frank', 'Male')
var person2 = new Person ('Mick', 'Female')

person1.speak() // Hi, I'm Frank!
person2.speak() // Hi, I'm Mick!

// 修改共同方法
Person.prototype.speak = function () {
  console.log('Hello, I\'m ' + this.name + '!')
}

//說話從Hi變成了Hello
person1.speak() // Hello, I'm Frank!
person2.speak() // Hello, I'm Mick!

這時候再使用開發者工具檢查 Person,會發現它的結構變成如下,只有兩個屬性,沒有打招呼的函式,理論上是無法說話,那為什麼 person1 還能說話呢? 發現他們參考到相同的源頭 _proto_

這個函數共用的概念,可以拿來做許多的應用,例如彈珠檯遊戲,每個球都有自己的位置和移動,我們就可以用這個概念去產出許多顆彈珠。

繼承 – 抽取出更抽象的類別

現在的物件產生器,不僅可以幫我們快速產出一個又一個的人,並且擁有一樣的函式。以為這樣就結束了嗎?太小看物件導向了。像是球球對打的遊戲中,球和兩個板子雖然完全不相干,但是我們可以發現,他們除了外型不同之外,其實有許多共同屬性與方法(例如x, y的座標、移動、碰撞),所以我們是不是可以依照需求,抽取出更抽象的類別。

js 內的繼承非常的麻煩,若是想要了解更詳細的內容,也可以參考動畫互動網頁特效入門(JS/CANVAS)課程。在課程內的範例,是以狗去繼承生物體的屬性。狗和人都是生物,都會有名字、生命長度…等基本屬性,但是狗自己又有品種、喜歡吃的東西等屬性和方法,這時候我們就可以執行繼承,讓狗除了自己特有的屬性外,還能夠繼承生物體本身的基本屬性。

剛剛我們已經製作好人的產生器,並且加了賦予他們說話能力的函式,現在我們多了一個新的類別 – 工作者WorkPerson,會有自己額外的屬性(自己的工作)。我們並不會想再把人的屬性寫一遍,額外多一筆工作的值,這種寫法非常地冗,該如何讓 WorkPerson 使用人的屬性呢?首先讓我們整理出這次的三個新名詞:

  1. 繼承:類別繼承到物件,產生的人都要能有這些方法, WorkPerson 要能回去參考 Person 說話的方法
  2. prototype:原型、不會動的
  3. _proto_:共同源頭

操作的步驟如下:

繼承者有原始的屬性可以使用 – call,WorkPerson 初始化時,要使用 Person 的屬性執行
我們把程式碼改寫成如下:

var Person = function (name, gender) {
  this.name = name
  this.gender = gender
}
Person.prototype.speak = function () {
  console.log('Hi, I\'m ' + this.name + '!')
}

// 錯誤寫法
var WorkPersonFalse = function (name, gender, work) {
  this.name = name
  this.gender = gender
  this.work = work
}

// 正確寫法 - 步驟1
var WorkPerson = function (name, gender, work) {
  Person.call(this, name, gender)
}
var person = new WorkPerson('Amy', 'Female', 'designer')

這時候我們可以從開發者工具看到 person 已經有 Person 宣告的屬性了。

但此時,我們發現 person 還不能參考到 Person 的方法 speak。所以我們接下來再做些處理

// 步驟 2 
var WorkPerson = function (name, gender, work) {
  Person.call(this, name, gender)
  this.work = work
}

// 錯誤寫法
WorkPerson.prototype = Person.prototype
// 正確寫法
WorkPerson.prototype = Object.create(Person.prototype)

WorkPerson.prototype.speakWork = function () {
  console.log('I\'m ' + this.work + '.')
}

var person = new WorkPerson('Amy', 'Female', 'designer')

那為什麼我們不能直接寫成 WorkPerson.prototype = Person.prototype 呢?

因為如果我們今天針對 WorkPerson.prototype.speak 去修改,也會連帶修改到 Person 中的 speak 方法,這並不是我們希望達到的效果,我們希望的只是 WorkPerson 參考 Person 的方法。

當用錯誤方式去宣告,造成 WorkPerson 有一個說自己工作的函式時, Person 也會有這個函式。

複寫

老闆在這邊也給大家一個小提示,今天當 WorkPerson 自己也有 speak 的函式時,它就會優先使用自己有的。當它沒有這個函式時,才會向它繼承的對象去找有沒有這個方法。

Person.prototype.speak = function () {
  console.log('I\'m ' + this.work + '.')
}

WorkPerson.prototype.speak = function () {
  console.log('Aloha.')
}

以上為物件導向的過程,大家可以一起跟著寫寫看,透過實際操作了解之中的差別。也因為現在工具越來越方便,比較少會去直接接觸到這些內容,若是大家想要對程式有更深的了解,我們建議大家還是可以去了解一下底層的概念。

動畫互動網頁特效入門(JS/CANVAS)課程裡面,分成三個章節在講物件導向:概念篇、繼承篇及實作篇,有更詳細的介紹,再完成一個小遊戲。

老闆來閒聊

另外老闆也跳出來和大家分享,在老闆進行網頁設計的過程,常用的一些軟體和工具。

網頁設計

老闆在製作遊戲前,都會先畫個草圖,來敘述遊戲配置和過關條件。製作網頁時,老闆會使用模板工具( Zeplin, Sketch, Illustrator.. )來做內部與外部的設計稿討論、tag 討論。 動畫互動網頁特效入門(JS/CANVAS)會和大家分享一些動態網頁的形式與實際應用,以及怎麼使用 Sketch 以及 Zeplin 來執行專案,有興趣想深入了解老闆怎麼利用這些工具進行設計,一樣可以支持一下老闆的課程。

後端 – firebase

老闆在這邊跟大家誠摯推薦 – firebase 。 firebase 可以做為後端資料庫使用外,也支援檔案上傳,取得 url 就可以直接將圖片引用到你的網站中。作品集若是使用 firebase 串的,若是在後台更改後,可以馬上在前端看到畫面上的變動。也可以利用 firebase 來製作權限功能,提供不同權限的人有不同功能。

案子分享 – 雜學校

這個案子屬於單頁式的 spa ,透過動態轉換,不會有換頁效果。也因為是單頁應用程式,所有狀態是同步的。現在的網站會把整個網站想像成一個應用程式,不像以往是一頁一頁區分的,好處是通用狀態不用存在後端 php session內,也不會有換頁必須要重整頁面的狀況。

這次的分享就到這邊,如果有甚麼問題,都歡迎私訊老闆 來點寇汀吧粉專,或是到我們的Instagram上看看最近都在玩些甚麼吧!

此篇直播筆記由幫手 H 協助整理

墨雨設計banner

訂閱 Creative Coding Taiwan 電子報:

這篇文章 基礎JS物件導向教學(直播筆記) 最早出現於 Creative Coding TW - 互動程式創作台灣站

]]>