共计 5959 个字符,预计需要花费 15 分钟才能阅读完成。
canvas 线段两端的款式
●canvas 中, 是能够设置线段两端的样子的
●咱们先来画三个平行线
// 0. 获取到页面上的 canvas 标签元素节点
const canvasEle = document.querySelector('#canvas')
// 1. 获取以后这个画布的工具箱
const ctx = canvasEle.getContext('2d')
// 2. 开始绘制第一个线段
// 第一个线段
ctx.moveTo(100, 100)
ctx.lineTo(200, 100)
ctx.lineWidth = 10
ctx.strokeStyle = '#000'
ctx.stroke()
ctx.beginPath()
// 第二个线段
ctx.moveTo(100, 150)
ctx.lineTo(200, 150)
ctx.lineWidth = 10
ctx.strokeStyle = '#000'
ctx.stroke()
ctx.beginPath()
// 第三个线段
ctx.moveTo(100, 200)
ctx.lineTo(200, 200)
ctx.lineWidth = 10
ctx.strokeStyle = '#000'
ctx.stroke()
ctx.beginPath()
●接下来, 咱们开始设置两端款式
语法: 工具箱.lineCap = ‘ 值 ’
值 :
=> butt 无
=> round 圆
=> square 方
// 0. 获取到页面上的 canvas 标签元素节点
const canvasEle = document.querySelector('#canvas')
// 1. 获取以后这个画布的工具箱
const ctx = canvasEle.getContext('2d')
// 2. 开始绘制第一个线段
// 第一个线段
ctx.moveTo(100, 100)
ctx.lineTo(200, 100)
ctx.lineWidth = 10
ctx.strokeStyle = '#000'
// 两端款式设置为 butt
ctx.lineCap = 'butt'
ctx.stroke()
ctx.beginPath()
// 第二个线段
ctx.moveTo(100, 150)
ctx.lineTo(200, 150)
ctx.lineWidth = 10
ctx.strokeStyle = '#000'
// 两端款式设置为 round
ctx.lineCap = 'round'
ctx.stroke()
ctx.beginPath()
// 第三个线段
ctx.moveTo(100, 200)
ctx.lineTo(200, 200)
ctx.lineWidth = 10
ctx.strokeStyle = '#000'
// 两端款式设置为 'square'
ctx.lineCap = 'square'
ctx.stroke()
ctx.beginPath()
●square 和 round 会让线段稍稍变长
●线段端点款式的色彩会和线段色彩保持一致
canvas 线段拐点的款式
●canvas 在绘制线段拐角的时候, 会主动进行闭合拐角
●咱们也能够通过设置, 来设置一下拐角的样子
●先来绘制三个带有拐角的线段
// 0. 获取到页面上的 canvas 标签元素节点
const canvasEle = document.querySelector('#canvas')
// 1. 获取以后这个画布的工具箱
const ctx = canvasEle.getContext('2d')
// 2. 开始绘制第一个线段
// 第一个线段
ctx.moveTo(100, 100)
ctx.lineTo(200, 150)
ctx.lineTo(100, 200)
ctx.lineWidth = 10
ctx.strokeStyle = '#000'
ctx.stroke()
ctx.beginPath()
// 第二个线段
ctx.moveTo(200, 100)
ctx.lineTo(300, 150)
ctx.lineTo(200, 200)
ctx.lineWidth = 10
ctx.strokeStyle = '#000'
ctx.stroke()
ctx.beginPath()
// 第三个线段
ctx.moveTo(300, 100)
ctx.lineTo(400, 150)
ctx.lineTo(300, 200)
ctx.lineWidth = 10
ctx.strokeStyle = '#000'
ctx.stroke()
ctx.beginPath()
●canvas 对于线段拐点默认的款式就是尖角拐点
●咱们能够进行一些设置来扭转
语法: 工具箱.lineJoin = ‘ 值 ’
值:
=> miter 默认尖角拐点
=> round 创立圆角拐点
=> bevel 创立斜角拐点
// 0. 获取到页面上的 canvas 标签元素节点
const canvasEle = document.querySelector('#canvas')
// 1. 获取以后这个画布的工具箱
const ctx = canvasEle.getContext('2d')
// 2. 开始绘制第一个线段
// 第一个线段
ctx.moveTo(100, 100)
ctx.lineTo(200, 150)
ctx.lineTo(100, 200)
ctx.lineWidth = 10
ctx.strokeStyle = '#000'
// 默认拐点
ctx.lineJoin = 'miter'
ctx.stroke()
ctx.beginPath()
// 第二个线段
ctx.moveTo(200, 100)
ctx.lineTo(300, 150)
ctx.lineTo(200, 200)
ctx.lineWidth = 10
ctx.strokeStyle = '#000'
// 圆角拐点
ctx.lineJoin = 'round'
ctx.stroke()
ctx.beginPath()
// 第三个线段
ctx.moveTo(300, 100)
ctx.lineTo(400, 150)
ctx.lineTo(300, 200)
ctx.lineWidth = 10
ctx.strokeStyle = '#000'
// 斜角拐点
ctx.lineJoin = 'bevel'
ctx.stroke()
ctx.beginPath()
canvas 填充
●在 canvas 中, 一旦你画出关闭图形当前
●咱们不光能够描边, 也能够进行填充, 也就是填满色彩
●先来画一个矩形吧
// 0. 获取到页面上的 canvas 标签元素节点
const canvasEle = document.querySelector('#canvas')
// 1. 获取以后这个画布的工具箱
const ctx = canvasEle.getContext('2d')
// 2. 开始绘制第一个线段
// 第一个线段
ctx.moveTo(100, 100)
ctx.lineTo(200, 100)
ctx.lineTo(200, 200)
ctx.lineTo(100, 200)
ctx.lineWidth = 2
ctx.strokeStyle = '#000'
ctx.closePath()
ctx.stroke()
●咱们这里用的是描边(工具箱.stroke() )
●是依照痕迹把路线描绘下来
●在 canvas 内, 除了描边, 还有一个叫做填充
●咱们再来一个矩形, 这次咱们不进行描边, 而是进行填充
// 0. 获取到页面上的 canvas 标签元素节点
const canvasEle = document.querySelector('#canvas')
// 1. 获取以后这个画布的工具箱
const ctx = canvasEle.getContext('2d')
// 2. 开始绘制第一个线段
// 第一个线段
ctx.moveTo(100, 100)
ctx.lineTo(200, 100)
ctx.lineTo(200, 200)
ctx.lineTo(100, 200)
// 3. 填充
// 语法: 工具箱.fill()
ctx.fill()
●这样, 就会依照咱们绘制的路线, 以填充的模式呈现一个关闭图形
●留神 : 填充的时候能够不进行图形闭合, 会主动闭合图形当前进行填充
●填充的时候也能够设置填充色彩的设置
// 0. 获取到页面上的 canvas 标签元素节点
const canvasEle = document.querySelector('#canvas')
// 1. 获取以后这个画布的工具箱
const ctx = canvasEle.getContext('2d')
// 2. 开始绘制第一个线段
// 第一个线段
ctx.moveTo(100, 100)
ctx.lineTo(200, 100)
ctx.lineTo(200, 200)
ctx.lineTo(100, 200)
// 3. 填充
// 3-1. 填充色彩设置
// 语法: 工具箱.fillStyle = '值'
ctx.fillStyle = 'skyblue'
// 3-2. 填充
ctx.fill()
●填充是能够和描边一起应用的
// 0. 获取到页面上的 canvas 标签元素节点
const canvasEle = document.querySelector('#canvas')
// 1. 获取以后这个画布的工具箱
const ctx = canvasEle.getContext('2d')
// 2. 开始绘制第一个线段
// 第一个线段
ctx.moveTo(100, 100)
ctx.lineTo(200, 100)
ctx.lineTo(200, 200)
ctx.lineTo(100, 200)
// 主动闭合图形
ctx.closePath()
// 3. 描边
// 3-1. 设置描边款式
ctx.lineWidth = 4
ctx.strokeStyle = 'orange'
// 3-2. 描边
ctx.stroke()
// 4. 填充
// 4-1. 填充色彩设置
ctx.fillStyle = 'skyblue'
// 4-2. 填充
ctx.fill()
canvas 的填充规定
●咱们发现, 到当初为止, canvas 的绘制, 描边, 填充都很简略
●然而接下来的内容可能略微简单一些了
●咱们要说一下 canvas 的填充规定
●咱们管 canvas 的填充规定叫做 非零填充
例子
●一下子可能说不明确, 咱们先来看一个例子
●绘制一个 “ 回 ” 形
●留神一个细节 :
○咱们绘制的过程
○外面的小正方形咱们会依照 顺时针 的方向绘制
○里面的大正方形咱们也会依照 顺时针 的方向绘制
// 0. 获取到页面上的 canvas 标签元素节点
const canvasEle = document.querySelector('#canvas')
// 1. 获取以后这个画布的工具箱
const ctx = canvasEle.getContext('2d')
// 2. 开始绘制外面的小正方形
ctx.moveTo(200, 100)
ctx.lineTo(300, 100)
ctx.lineTo(300, 200)
ctx.lineTo(200, 200)
ctx.lineWidth = 2
ctx.strokeStyle = '#000'
ctx.stroke()
// 3. 开始绘制里面的大正方形
ctx.moveTo(150, 50)
ctx.lineTo(350, 50)
ctx.lineTo(350, 250)
ctx.lineTo(150, 250)
ctx.stroke()
●两个正方形都是这个方向绘制的, 咱们接下来把描边的线去掉
●咱们来进行一下填充看看
// 0. 获取到页面上的 canvas 标签元素节点
const canvasEle = document.querySelector('#canvas')
// 1. 获取以后这个画布的工具箱
const ctx = canvasEle.getContext('2d')
// 2. 开始绘制外面的小正方形
ctx.moveTo(200, 100)
ctx.lineTo(300, 100)
ctx.lineTo(300, 200)
ctx.lineTo(200, 200)
// ctx.lineWidth = 2
// ctx.strokeStyle = '#000'
// ctx.stroke()
// 3. 开始绘制里面的大正方形
ctx.moveTo(150, 50)
ctx.lineTo(350, 50)
ctx.lineTo(350, 250)
ctx.lineTo(150, 250)
// ctx.stroke()
// 4. 填充
ctx.fill()
●咱们发现, 两个都被填充了
●这是因为, 在填充的时候, 就是会一次性把所有的内容都会填充好
●留神 :
○和是否闭合门路 (工具箱.closePath() ) 没有关系
○和里外正方形的绘制先后顺序没有关系
●那是怎么回事呢 ?
例子
●先不论是怎么回事, 咱们再来看一个例子
●还是绘制一个 “ 回 ” 形
●留神一个细节 :
○咱们绘制的过程
○外面的小正方形咱们会依照 逆时针 的方向绘制
○里面的大正方形咱们也会依照 顺时针 的方向绘制
// 0. 获取到页面上的 canvas 标签元素节点
const canvasEle = document.querySelector('#canvas')
// 1. 获取以后这个画布的工具箱
const ctx = canvasEle.getContext('2d')
// 2. 开始绘制外面的小正方形
ctx.moveTo(200, 100)
ctx.lineTo(200, 200)
ctx.lineTo(300, 200)
ctx.lineTo(300, 100)
ctx.lineWidth = 2
ctx.strokeStyle = '#000'
ctx.stroke()
// 3. 开始绘制里面的大正方形
ctx.moveTo(150, 50)
ctx.lineTo(350, 50)
ctx.lineTo(350, 250)
ctx.lineTo(150, 250)
ctx.stroke()
●这回两个矩形绘制的时候, 方向不一样了
●咱们再来填充一次试试看
●咱们会发现, 和方才填充进去的后果不一样了
●这又是怎么回事呢 ?
●难道和顺时针逆时针有关系吗 ?
非零填充
●其实咱们的填充和顺时针逆时针有关系, 然而不是简略的顺逆时针的问题
●概念 :
○从任何一个区域向画布最外层挪动
○依照经验最短边计算
○其中经验的顺时针的边记录为 +1
○经验逆时针的边记录为 -1
○只有最终总和不为 零, 那么该区域填充
○如果最终总和为 零, 那么该区域不填充
●听起来很麻烦, 咱们来画布上看一下成果就好了
●这次咱们绘制一个略微简单一些的图形
●这是两个矩形对接在一起, 一个是顺时针绘制, 一个是逆时针绘制
●咱们来剖析一下看看
●首先, 最左侧关闭图形
○如果走最短的路线进去的话, 会经验一条顺时针的边
○记录为 +1
○最终为 +1
○所以该区域填充
●而后, 最右侧关闭图形
○经验最短路线进去的话, 会经验一条逆时针的边
○记录为 -1
○最终为 -1
○所以该区域填充
●最初, 两头的关闭图形
○经验最短路线进去的会, 必然会经验一条顺时针的边和一条逆时针的边
○顺时针记录为 +1
○逆时针记录为 -1
○最终为 0
○所以该区域不填充
●此时咱们对以后图形进行填充后察看
●这就是最初填充好的样子