流水賬系列之Canvas繪製-02

答案xxz發表於2019-03-21

繪製矩形

// 填充矩形
ctx.fillRect(
    // x y
    10, 10,
    // width height
    120, 120
)
// 描邊矩形
ctx.strokeRect(
    // x y
    180, 10,
    // width height
    120, 120
)
// 清除矩形:將指定矩形與當前剪輯區域相交範圍內所有畫素清除
ctx.clearRect(
    // x y
    0, 0,
    // width height
    canvas.width, canvas.height
)
複製程式碼

畫素清除

將其顏色設定為全透明的黑色,等同於清除某個畫素

圖示

流水賬系列之Canvas繪製-02

樣式設定

API

// 設定描邊樣式
ctx.strokeStyle="color|gradient|pattern"
// 設定填充樣式
ctx.fillStyle="color|gradient|pattern"
複製程式碼

設定顏色

ctx.strokeStyle = 'red'
ctx.fillStyle = 'rgba(0,0,0,0.5)'
ctx.fillStyle = '#000'
複製程式碼

設定漸變色

線性漸變

點1到點2的線性漸變

const gradient = ctx.createLinearGradient(
    // 點1
    x1, y1,
    // 點2
    x2, y2
)

gradient.addColorStop(0, 'blue')
gradient.addColorStop(0.25, 'yellow')
gradient.addColorStop(0.8, 'pink')
複製程式碼
流水賬系列之Canvas繪製-02

放射漸變

x1,y1為圓心,半徑為radius1的圓 到 以x2,y2為圓心,半徑為radius2的圓 的放射漸變

const gradient = ctx.createRadialGradient(
    // x1, y1, radius1
    canvas.width / 2, 0, 10,
    // x2, y2, radius2
    canvas.width / 2, canvas.height, 100
)
// 顏色停止點 ([0~1],'color')
gradient.addColorStop(0, 'blue')
gradient.addColorStop(0.25, 'yellow')
gradient.addColorStop(0.8, 'pink')
複製程式碼
流水賬系列之Canvas繪製-02

設定圖案

const image = new Image()
image.src = '/img/redball.png'
image.onload = () => {
    ctx.fillStyle = ctx.createPattern(
      image,
      // 圖案重複情況 repeat-x no-repeat...
      'repeat'
    )
    ctx.fillRect(
      0, 0,
      canvas.width, canvas.height
    )
}
複製程式碼
流水賬系列之Canvas繪製-02

陰影

偏移量為負數有內嵌陰影的效果,陰影顏色建議用帶透明度的顏色

// x 偏移
ctx.shadowOffsetX = 4
// y 偏移
ctx.shadowOffsetY = 6
// 陰影顏色
ctx.shadowColor = 'rgba(0,0,0,1)'
// 高斯模糊
ctx.shadowBlur = 10
ctx.strokeRect(10, 10, 100, 100)
複製程式碼

路徑

繪製方法

// 使用fillStyle對當前路徑的內部進行填充
ctx.fill()
// 使用strokeStyle來描繪當前路徑的輪廓線
ctx.stroke()
複製程式碼

路徑形狀

需要呼叫fill()或stroke()進行繪製

** 建立路徑後對齊進行描邊或填充**

  • 好比使用隱形筆繪製好(rect,arc)
  • 然後用加熱等讓其顯式出來(stroke,fill)
// 繪製矩形路徑。預設是逆時針繪製
ctx.rect(
    // x  y
    40, 120,
    // width  height
    100, 100
)
// 圓弧路徑
ctx.arc(
    x,y,
    radius,
    startAngle,endAngle,
    // 逆時針
    anticlockwise=false
)

// 圓弧之 arcTo

複製程式碼

beginPath和closePath

// 將當前路徑之中的所有子路徑都清除,重置當前路徑,在需要開始一段新的路徑時,需要呼叫此方法
ctx.beginPath()
// 顯式封閉某段開放路徑
ctx.closePath()
複製程式碼

對比有無beginPath

ctx.beginPath() // 1
ctx.strokeStyle = 'blue'
ctx.lineWidth = 10
ctx.rect(50, 50, 100, 100)
ctx.stroke()

// 沒有開始新的路徑,會從1處再次繪製
ctx.strokeStyle = 'red'
ctx.lineWidth = 5
ctx.rect(50, 200, 100, 100)
ctx.stroke()


ctx.beginPath() // -> 2
ctx.strokeStyle = 'blue'
ctx.lineWidth = 10
ctx.rect(250, 50, 100, 100)
ctx.stroke()

// 此處開始了新的路徑
ctx.beginPath()
ctx.strokeStyle = 'red'
ctx.lineWidth = 5
ctx.rect(250, 200, 100, 100)
ctx.stroke()
複製程式碼

左邊一列的明顯將左上的矩形再次繪製了一次

流水賬系列之Canvas繪製-02

對比有無closePath

主要用於封閉圓弧路徑或由曲線或線段組成的開放路徑

ctx.beginPath()
ctx.arc(100, 100, 40, 0, Math.PI * 3 / 2)
ctx.stroke()

ctx.beginPath()
ctx.arc(240, 100, 40, 0, Math.PI * 3 / 2)
ctx.closePath()
ctx.stroke()
複製程式碼
流水賬系列之Canvas繪製-02

非零環繞規則

定義

只要位置上存在包含關係的繪製方向不一致即有剪紙效果

ctx.shadowBlur = 10
ctx.shadowOffsetX = 2
ctx.shadowOffsetY = 10
ctx.shadowColor = 'rgba(0,0,0,0.3)'

ctx.beginPath()
// 只要兩個圓弧的繪製方向不一致即可有剪紙效果
ctx.arc(160, 160, 100, 0, Math.PI * 2)
ctx.arc(160, 160, 50, 0, Math.PI * 2, true)
ctx.fill()
複製程式碼
流水賬系列之Canvas繪製-02

線段

ctx.moveTo(x, y)
ctx.lineTo(x, y)
複製程式碼

線段及邊界

ctx.beginPath()
ctx.moveTo(40, 40)
ctx.lineTo(200, 40)
ctx.stroke()

ctx.beginPath()
ctx.moveTo(40, 80.5)
ctx.lineTo(200, 80.5)
ctx.stroke()
複製程式碼

第一條線感覺有2px

流水賬系列之Canvas繪製-02

邊界問題

流水賬系列之Canvas繪製-02 流水賬系列之Canvas繪製-02

網格

// 參考畫素邊界
ctx.lineWidth = 0.5

// 水平方向
for (let i = stepX; i < canvas.width; i += stepX) {
    ctx.beginPath()
    ctx.moveTo(i, 0)
    ctx.lineTo(i, canvas.height)
    ctx.stroke()
}

// 垂直方向
for (let i = stepY; i < canvas.height; i += stepY) {
    ctx.beginPath()
    ctx.moveTo(0, i)
    ctx.lineTo(canvas.width, i)
    ctx.stroke()
}
複製程式碼
流水賬系列之Canvas繪製-02

座標系

流水賬系列之Canvas繪製-02

橡皮筋繪製線條

在handleMouseDown記錄線段開始位置,handleMouseMove儲存線段結束位置,handleMouseUp儲存拖動線段資料

流水賬系列之Canvas繪製-02

擴充套件虛線繪製

繪製上下文ctx的類是CanvasRenderingContext2D

const moveToFn = CanvasRenderingContext2D.prototype.moveTo
CanvasRenderingContext2D.prototype.lastMoveToData = {}
CanvasRenderingContext2D.prototype.moveTo = function (x, y) {
  // 劫持原生moveTo
  moveToFn.apply(this, [ x, y ])
  // 保留moveTo位置
  this.lastMoveToData = {
    x, y
  }
}
// 擴充套件dashedTo
CanvasRenderingContext2D.prototype.dashedTo = function (x, y, dashLength = 5) {
  const { x: startX, y: startY } = this.lastMoveToData
  const deltaX = x - startX
  const deltaY = y - startY

  const dashedNum = Math.floor(
    Math.sqrt(
      deltaX * deltaX + deltaY * deltaY
    ) / dashLength
  )

  for (let i = 0; i < dashedNum; i++) {
    const fn = i % 2 === 0 ? 'moveTo' : 'lineTo'
    this[ fn ](
      startX + deltaX / dashedNum * i,
      startY + deltaY / dashedNum * i
    )
  }
}

複製程式碼

使用

ctx.beginPath()
ctx.moveTo(100, 100)
ctx.dashedTo(200, 200)
ctx.stroke()
複製程式碼

線段端點

ctx.lineCap = 'butt'    // 預設
ctx.lineCap = 'square'  // 方塊
ctx.lineCap = 'round'   // 圓角
複製程式碼
流水賬系列之Canvas繪製-02

連線點繪製

// 線寬度
ctx.lineWidth = 20

ctx.lineJoin = 'miter'
ctx.lineJoin = 'round'
ctx.lineJoin = 'bevel'
複製程式碼
流水賬系列之Canvas繪製-02

橡皮筋畫圓

數學知識

貝塞爾曲線

二次貝塞爾曲線

只向一個方向彎曲的簡單曲線

ctx.quadraticCurveTo(
    // 控制點
    180, 180,
    // 錨點
    200, 100
)
複製程式碼

紅色點是控制點,藍色點是錨點

流水賬系列之Canvas繪製-02

相關文章