国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

可擴(kuò)展面向?qū)ο蟮腸anvas畫圖程序

Lavender / 1430人閱讀

摘要:方法創(chuàng)建弧曲線用于創(chuàng)建圓或部分圓圓的中心的坐標(biāo)。弧的圓形的三點(diǎn)鐘位置是度。規(guī)定應(yīng)該逆時(shí)針還是順時(shí)針繪圖。注意事項(xiàng)構(gòu)造函數(shù)的形參只有兩個(gè)是必須的,就是定位點(diǎn)的坐標(biāo)。選中元素時(shí)調(diào)用,判斷選中位置。

面向?qū)ο蟮腸anvas畫圖程序 項(xiàng)目簡(jiǎn)介

整個(gè)項(xiàng)目分為兩大部分

場(chǎng)景
場(chǎng)景負(fù)責(zé)canvas控制,事件監(jiān)聽,動(dòng)畫處理

精靈
精靈則指的是每一種可以繪制的canvas元素

Demo演示地址
Demo為最新代碼

項(xiàng)目特點(diǎn)

可擴(kuò)展性強(qiáng)

sprite精靈實(shí)現(xiàn) 父類
class Element {
  constructor(options = {
    fillStyle: "rgba(0,0,0,0)",
    lineWidth: 1,
    strokeStyle: "rgba(0,0,0,255)"
  }) {
    this.options = options
  }
  setStyle(options){
    this.options =  Object.assign(this.options. options)
  }
}

屬性:

options中存儲(chǔ)了所有的繪圖屬性

fillStyle:設(shè)置或返回用于填充繪畫的顏色、漸變或模式

strokeStyle:設(shè)置或返回用于筆觸的顏色、漸變或模式

lineWidth:設(shè)置或返回當(dāng)前的線條寬度

使用的都是getContext("2d")對(duì)象的原生屬性,此處只列出了這三種屬性,需要的話還可以繼續(xù)擴(kuò)充。

有需要可以繼續(xù)擴(kuò)充

方法:

setStyle方法用于重新設(shè)置當(dāng)前精靈的屬性

有需要可以繼續(xù)擴(kuò)充

所有的精靈都繼承Element類。

子類

子類就是每一種精靈元素的具體實(shí)現(xiàn),這里我們介紹一遍Circle元素的實(shí)現(xiàn)

class Circle extends Element {
  // 定位點(diǎn)的坐標(biāo)(這塊就是圓心),半徑,配置對(duì)象
  constructor(x, y, r = 0, options) {
    // 調(diào)用父類的構(gòu)造函數(shù)
    super(options)
    this.x = x
    this.y = y
    this.r = r
  }
  // 改變?cè)卮笮?  resize(x, y) {
    this.r = Math.sqrt((this.x - x) ** 2 + (this.y - y) ** 2)
  }
  // 移動(dòng)元素到新位置,接收兩個(gè)參數(shù),新的元素位置
  moveTo(x, y) {
    this.x = x
    this.y = y
  }
  // 判斷點(diǎn)是否在元素中,接收兩個(gè)參數(shù),點(diǎn)的坐標(biāo)
  choose(x, y) {
    return ((x - this.x) ** 2 + (y - this.y) ** 2) < (this.r ** 2)
  }
  // 偏移,計(jì)算點(diǎn)和元素定位點(diǎn)的相對(duì)偏移量(ofsetX, offsetY)
  getOffset(x, y) {
    return {
      x: x - this.x,
      y: y - this.y
    }
  }
  // 繪制元素實(shí)現(xiàn),接收一個(gè)ctx對(duì)象,將當(dāng)前元素繪制到指定畫布上
  draw(ctx) {
    // 取到繪制所需屬性
    let {
      fillStyle,
      strokeStyle,
      lineWidth
    } = this.options
    // 開始繪制beginPath() 方法開始一條路徑,或重置當(dāng)前的路徑
    ctx.beginPath()
    // 設(shè)置屬性
    ctx.fillStyle = fillStyle
    ctx.strokeStyle = strokeStyle
    ctx.lineWidth = lineWidth
    // 畫圓
    ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI)
    // 填充顏色
    ctx.stroke()
    ctx.fill()
    // 繪制完成
  }
  // 驗(yàn)證函數(shù),判斷當(dāng)前元素是否滿足指定條件,此處用來檢驗(yàn)是否將元素添加到場(chǎng)景中。
  validate() {
    return this.r >= 3
  }
}

arc() 方法創(chuàng)建弧/曲線(用于創(chuàng)建圓或部分圓)

x 圓的中心的 x 坐標(biāo)。

y 圓的中心的 y 坐標(biāo)。

r 圓的半徑。

sAngle 起始角,以弧度計(jì)。(弧的圓形的三點(diǎn)鐘位置是 0 度)。

eAngle 結(jié)束角,以弧度計(jì)。

counterclockwise 可選。規(guī)定應(yīng)該逆時(shí)針還是順時(shí)針繪圖。False = 順時(shí)針,true = 逆時(shí)針。

注意事項(xiàng):

構(gòu)造函數(shù)的形參只有兩個(gè)是必須的,就是定位點(diǎn)的坐標(biāo)。

其它的形參都必須有默認(rèn)值。

所有方法的調(diào)用時(shí)機(jī)

我們?cè)诋嫴忌侠L制元素的時(shí)候回調(diào)用resize方法。

移動(dòng)元素的時(shí)候調(diào)用moveTo方法。

choose會(huì)在鼠標(biāo)按下時(shí)調(diào)用,判斷當(dāng)前元素是否被選中。

getOffset選中元素時(shí)調(diào)用,判斷選中位置。

draw繪制函數(shù),繪制元素到場(chǎng)景上時(shí)調(diào)用。

scene場(chǎng)景的實(shí)現(xiàn)

屬性介紹

class Sence {
  constructor(id, options = {
    width: 600,
    height: 400
  }) {
    // 畫布屬性
    this.canvas = document.querySelector("#" + id)
    this.canvas.width = options.width
    this.canvas.height = options.height
    this.width = options.width
    this.height = options.height
    // 繪圖的對(duì)象
    this.ctx = this.canvas.getContext("2d")
    // 離屏canvas
    this.outCanvas = document.createElement("canvas")
    this.outCanvas.width = this.width
    this.outCanvas.height = this.height
    this.outCtx = this.outCanvas.getContext("2d")
    // 畫布狀態(tài)
    this.stateList = {
      drawing: "drawing",
      moving: "moving"
    }
    this.state = this.stateList.drawing
    // 鼠標(biāo)狀態(tài)
    this.mouseState = {
    // 記錄鼠標(biāo)按下時(shí)的偏移量
      offsetX: 0,
      offsetY: 0,
      down: false, //記錄鼠標(biāo)當(dāng)前狀態(tài)是否按下
      target: null //當(dāng)前操作的目標(biāo)元素
    }
    // 當(dāng)前選中的精靈構(gòu)造器
    this.currentSpriteConstructor = null
    // 存儲(chǔ)精靈
    let sprites = []
    this.sprites = sprites
    /* .... */
  }
}

事件邏輯

class Sence {
  constructor(id, options = {
    width: 600,
    height: 400
  }) {
  /* ... */
  // 監(jiān)聽事件
    this.canvas.addEventListener("contextmenu", (e) => {
      console.log(e)
    })
    // 鼠標(biāo)按下時(shí)的處理邏輯
    this.canvas.addEventListener("mousedown", (e) => {
    // 只有左鍵按下時(shí)才會(huì)處理鼠標(biāo)事件
      if (e.button === 0) {
      // 鼠標(biāo)的位置
        let x = e.offsetX
        let y = e.offsetY
        // 記錄鼠標(biāo)是否按下
        this.mouseState.down = true
        // 創(chuàng)建一個(gè)臨時(shí)target
        // 記錄目標(biāo)元素
        let target = null
        if (this.state === this.stateList.drawing) {
        // 判斷當(dāng)前有沒有精靈構(gòu)造器,有的話就構(gòu)造一個(gè)對(duì)應(yīng)的精靈元素
          if (this.currentSpriteConstructor) {
            target = new this.currentSpriteConstructor(x, y)
          }
        } else if (this.state === this.stateList.moving) {
          let sprites = this.sprites
          // 遍歷所有的精靈,調(diào)用他們的choose方法,判斷有沒有被選中
          for (let i = sprites.length - 1; i >= 0; i--) {
            if (sprites[i].choose(x, y)) {
              target = sprites[i]
              break;
            }
          }
          
          // 如果選中的話就調(diào)用target的getOffset方法,獲取偏移量
          if (target) {
            let offset = target.getOffset(x, y)
            this.mouseState.offsetX = offset.x
            this.mouseState.offsetY = offset.y
          }
        }
        // 存儲(chǔ)當(dāng)前目標(biāo)元素
        this.mouseState.target = target
        // 在離屏canvas保存除目標(biāo)元素外的所有元素
        let ctx = this.outCtx
        // 清空離屏canvas
        ctx.clearRect(0, 0, this.width, this.height)
        // 將目標(biāo)元素外的所有的元素繪制到離屏canvas中
        this.sprites.forEach(item => {
          if (item !== target) {
            item.draw(ctx)
          }
        })
        if(target){
            // 開始動(dòng)畫
            this.anmite()
        }
      }
    })
    this.canvas.addEventListener("mousemove", (e) => {
    //  如果鼠標(biāo)按下且有目標(biāo)元素,才執(zhí)行下面的代碼
      if (this.mouseState.down && this.mouseState.target) {
        let x = e.offsetX
        let y = e.offsetY
        if (this.state === this.stateList.drawing) {
        // 調(diào)用當(dāng)前target的resize方法,改變大小
          this.mouseState.target.resize(x, y)
        } else if (this.state === this.stateList.moving) {
        // 取到存儲(chǔ)的偏移量
          let {
            offsetX, offsetY
          } = this.mouseState
          // 調(diào)用moveTo方法將target移動(dòng)到新的位置
          this.mouseState.target.moveTo(x - offsetX, y - offsetY)
        }
      }
    })
    document.body.addEventListener("mouseup", (e) => {
      if (this.mouseState.down) {
      // 將鼠標(biāo)按下狀態(tài)記錄為false
        this.mouseState.down = false
        if (this.state === this.stateList.drawing) {
        // 調(diào)用target的validate方法。判斷他要不要被加到場(chǎng)景去呢
          if (this.mouseState.target.validate()) {
            this.sprites.push(this.mouseState.target)
          }
        } else if (this.state === this.stateList.moving) {
          // 什么都不做
        }
      }
    })
  }
}

方法介紹

class Sence {
// 動(dòng)畫
  anmite() {
    requestAnimationFrame(() => {
      // 清除畫布
      this.clear()
      // 將離屏canvas繪制到當(dāng)前canvas上
      this.paint(this.outCanvas)
      // 繪制target
      this.mouseState.target.draw(this.ctx)
      // 鼠標(biāo)是按下狀態(tài)就繼續(xù)執(zhí)行下一幀動(dòng)畫
      if (this.mouseState.down) {
        this.anmite()
      }
    })
  }
  // 可以將手動(dòng)的創(chuàng)建的精靈添加到畫布中
  append(sprite) {
    this.sprites.push(sprite)
    sprite.draw(this.ctx)
  }
  // 根據(jù)ID值,從場(chǎng)景中刪除對(duì)應(yīng)元素
  remove(id) {
    this.sprites.splice(id, 1)
  }
  // clearRect清除指定區(qū)域的畫布內(nèi)容
  clear() {
    this.ctx.clearRect(0, 0, this.width, this.height)
  }
  // 重繪整個(gè)畫布的內(nèi)容
  reset() {
    this.clear()
    this.sprites.forEach(element => {
      element.draw(this.ctx)
    })
  }
  // 將離屏canvas繪制到頁面的canvas畫布上
  paint(canvas, x = 0, y = 0) {
    this.ctx.drawImage(canvas, x, y, this.width, this.height)
  }
  // 設(shè)置當(dāng)前選中的精靈構(gòu)造器
  setCurrentSprite(Element) {
    this.currentSpriteConstructor = Element
  }
}

Demo演示地址

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/96460.html

相關(guān)文章

  • canvas實(shí)現(xiàn)矩形畫圖效果

    摘要:主要實(shí)現(xiàn)功能在畫布上跟隨鼠標(biāo)的按鍵移動(dòng)畫出拖拉范圍內(nèi)的矩形彈出選擇項(xiàng),選對(duì)勾則將這部分矩形填上背景色,選叉號(hào)則取消本次拖拉的矩形。附業(yè)務(wù)目的視頻遮罩是一種將視頻某部分區(qū)域遮蓋的效果,可用于遮蓋電視臺(tái)圖標(biāo),廣告,鏡頭內(nèi)敏感部分等。 作者:云荒杯傾 序 本意是用這個(gè)做視頻遮罩效果,但是還是從更通用的角度來解釋事情本身吧。少摻雜一點(diǎn)業(yè)務(wù)目的。 主要實(shí)現(xiàn)功能 在canvas畫布上跟隨鼠標(biāo)的按鍵...

    TalkingData 評(píng)論0 收藏0
  • 項(xiàng)目中引入特殊字體【小程序、h5】包括canvas畫圖

    摘要:小程序和的頁面展示特殊字體有一個(gè)網(wǎng)站,叫有字庫。這就是直接再頁面上顯示文字的辦法這個(gè)在和小程序上面都可以使用的,非常方便。接下來就是畫圖了。引入就是用小程序的引入字體方法啦。 請(qǐng)看清楚我虛線下面所有的話。橫線上的廢話隨便你看不看。說實(shí)話這個(gè)字體已經(jīng)把我折騰的死去活來了一段時(shí)間,而且我們項(xiàng)目還經(jīng)常要畫分享圖去刷朋友圈,默認(rèn)字體沒辦法達(dá)到設(shè)計(jì)的那種效果,查了不少資料,也自己摸索了半天,最后...

    gotham 評(píng)論0 收藏0
  • 項(xiàng)目中引入特殊字體【小程序、h5】包括canvas畫圖

    摘要:小程序和的頁面展示特殊字體有一個(gè)網(wǎng)站,叫有字庫。這就是直接再頁面上顯示文字的辦法這個(gè)在和小程序上面都可以使用的,非常方便。接下來就是畫圖了。引入就是用小程序的引入字體方法啦。 請(qǐng)看清楚我虛線下面所有的話。橫線上的廢話隨便你看不看。說實(shí)話這個(gè)字體已經(jīng)把我折騰的死去活來了一段時(shí)間,而且我們項(xiàng)目還經(jīng)常要畫分享圖去刷朋友圈,默認(rèn)字體沒辦法達(dá)到設(shè)計(jì)的那種效果,查了不少資料,也自己摸索了半天,最后...

    pcChao 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<