Canvas初见

134 阅读4分钟

开启VSCode代码提示

js里写

/** @type {HTMLCanvasElement} */

创建基本图形

<canvas id="c1" width="600" height="300" style="position:relative;z-index: 1;">
    浏览器不支持Canvas,没有canvas的滚出克
</canvas>
let c1 = document.getElementById("c1")
let ctx = c1.getContext('2d')
矩形(rect)
// 填充的矩形
// 矩形 x,y 宽,高
ctx.fillRect(100,100,300,300)
​
// 线组成的矩形
ctx.strokeRect(100, 10, 300, 300)
ctx.fillRect(100, 10, 100, 100)
独立区域
ctx.beginPath()
ctx.rect(10, 10, 100, 100)
ctx.stroke()
ctx.closePath()
圆(arc)
// x,y,半径,起始角度,结束角,(顺逆时针 默认false顺时针 true逆时针)
// moveTo 绘制不连续的路径 移动原点到某个位置
ctx.beginPath()
ctx.arc(100, 100, 100, 0, Math.PI * 2)
ctx.moveTo(150,100)
​
ctx.arc(100, 100, 50, 0, Math.PI)
ctx.moveTo(85, 35)
​
ctx.arc(75, 35, 10, 0, Math.PI)
ctx.moveTo(135, 35)
​
ctx.arc(125, 35, 10, 0, Math.PI)
ctx.stroke()
ctx.closePath()
擦除(clear)
let height = 0;
let timer = setInterval(() => {
    height++
    ctx.clearRect(0, 0, c1.clientWidth, height)
    if (height > c1.clientHeight) {
        clearInterval(timer)
    }
}, 10)
圆弧(arcTo)
 //  arc 原点到 x1,y1 到 x2,y2
ctx.beginPath()
ctx.moveTo(100,100)
//x,y | x,y  半径
ctx.arcTo(170,100,50,3,30)
ctx.stroke()
ctx.closePath()
quadraticCurveTo()

CanvasRenderingContext2D.quadraticCurveTo() 是 Canvas 2D API 新增二次贝塞尔曲线路径的方法。它需要 2 个点。第一个点是控制点,第二个点是终点。起始点是当前路径最新的点,当创建二次贝赛尔曲线之前,可以使用 moveTo() 方法进行改变。

第一个为原点

ctx.quadraticCurveTo(cpx, cpy, x, y);
​
cpx
控制点的 x 轴坐标。
​
cpy
控制点的 y 轴坐标。
​
x
终点的 x 轴坐标。
​
y
终点的 y 轴坐标。
bezierCurveTo()
CanvasRenderingContext2D.bezierCurveTo() 是 Canvas 2D API 绘制三次贝赛尔曲线路径的方法。该方法需要三个点。第一、第二个点是控制点,第三个点是结束点。起始点是当前路径的最后一个点,绘制贝赛尔曲线前,可以通过调用 moveTo() 进行修改。
路径(path)
// 路径
var heartPath = new Path2D()
heartPath.moveTo(200, 120)
heartPath.bezierCurveTo(80, 20, 50, 220, 200, 250)
heartPath.bezierCurveTo(350, 220, 320, 20, 200, 120)
渐变(gradient)
createLinearGradient
let lineColor = ctx.createLinearGradient(0, 0, 650, 0)
lineColor.addColorStop(0, '#e03131')
lineColor.addColorStop(index, '#ff8787')
lineColor.addColorStop(1, '#ffc9c9')
createConicGradient
let lineColor = ctx.createConicGradient(Math.PI/6, 120, 10)

lineColor.addColorStop(0, '#e03131')
lineColor.addColorStop(.2, '#22b8cf')
lineColor.addColorStop(1, '#ffc9c9')
image
let img = new Image;
img.src = "./image/柴郡.jpg"

img.onload = ()=>{
    var partten = ctx.createPattern(img,"repeat")
    ctx.fillStyle = partten;
    ctx.fillRect(0,0,600,200)
}
line
ctx.lineWidth = 1;

// butt
// 线段末端以方形结束。

// round
// 线段末端以圆形结束。

// square
// 线段末端以方形结束,但是增加了一个宽度和线段相同,高度是线段厚度一半的矩形区域。
ctx.lineCap = "round"

// round
// 通过填充一个额外的,圆心在相连部分末端的扇形,绘制拐角的形状。圆角的半径是线段的宽度。

// bevel
// 在相连部分的末端填充一个额外的以三角形为底的区域,每个部分都有各自独立的矩形拐角。

// miter
// 通过延伸相连部分的外边缘,使其相交于一点,形成一个额外的菱形区域。这个设置可以通过 miterLimit 属性看到效果。
ctx.lineJoin = "mitter"

// 虚线模式 传入间隔数组
ctx.setLineDash([1,2,3,4])
video
// 图片 影音
var video = document.querySelector("video")

var btn = document.getElementById("btn")

var img = new Image()
img.src = "./image/柴郡.jpg"
btn.onclick = function () {
    video.play()
    render()
}

function render() {
    ctx.drawImage(video, 0, 0, 600, 400)

    ctx.drawImage(img,500,10,200,100)

    requestAnimationFrame(render)
}

案例

<canvas id="c1" width="600" height="300" style="position:relative;z-index: 1;">
    浏览器不支持Canvas
</canvas>
<br>
<button class="thickline button">粗线条</button>
<button class="thinline button active">细线条</button>
<button class="saveImg">保存图片</button>
<input type="color" name="" id="colorIpt">
<button class="rubber button">橡皮擦</button>
<button class="clearImg">清空画板</button>

script

 /** @type {HTMLCanvasElement} */
    let c1 = document.getElementById("c1")
    let ctx = c1.getContext('2d')

    let thinkBtn = document.querySelector(".thickline")
    let thinBtn = document.querySelector(".thinline")
    let saveBtn = document.querySelector(".saveImg")
    let colorBtn = document.querySelector("#colorIpt")
    let clearBtn = document.querySelector(".clearImg")
    let rubberBtn = document.querySelector(".rubber")

    ctx.fillStyle = "#fff"
    ctx.fillRect(0, 0, 600, 300)
    ctx.lineJoin = "round"
    ctx.lineCap = "round"
    ctx.lineWidth = 3;
    var isDraw = false;


    c1.onmousedown = (e) => {
      isDraw = true;
      ctx.beginPath()
      let x = e.pageX - c1.offsetLeft;
      let y = e.pageY - c1.offsetTop;
      ctx.moveTo(x, y)
    }
    c1.ontouchstart = (e) => {
      let ev = e.targetTouches[0]
      isDraw = true;
      ctx.beginPath()
      let x = ev.pageX - c1.offsetLeft;
      let y = ev.pageY - c1.offsetTop;
      ctx.moveTo(x, y)
    }

    c1.onmouseup = (e) => {
      isDraw = false;
      ctx.closePath()
    }
    c1.ontouchcancel = (e) => {
      isDraw = false;
      ctx.closePath()
    }
    c1.onmouseleave = (e) => {
      isDraw = false;
      ctx.closePath()
    }
    c1.ontouchend = (e) => {
      isDraw = false;
      ctx.closePath()
    }

    c1.onmousemove = (e) => {
      if (isDraw) {
        let x = e.pageX - c1.offsetLeft;
        let y = e.pageY - c1.offsetTop;
        ctx.lineTo(x, y)
        ctx.stroke()
      } else {
      }
    }
    c1.ontouchmove = (e) => {
      let ev = e.targetTouches[0]
      if (isDraw) {
        let x = ev.pageX - c1.offsetLeft;
        let y = ev.pageY - c1.offsetTop;
        ctx.lineTo(x, y)
        ctx.stroke()
      } else {
      }
    }

    // 清空
    clearBtn.onclick = () => {
      ctx.clearRect(0, 0, 600, 300);
    }

    // 橡皮擦
    rubberBtn.onclick = () => {
      // ctx.clearRect(0, 0, 600, 300);
      ctx.globalCompositeOperation = "destination-out"
      ctx.lineWidth = 30
      rubberBtn.classList.add("active")
      thinkBtn.classList.remove("active")
      thinBtn.classList.remove("active")
    }

    // 粗线条
    thinkBtn.onclick = () => {
      ctx.globalCompositeOperation = "source-over"
      ctx.lineWidth = 16;
      thinkBtn.classList.add("active")
      thinBtn.classList.remove("active")
      rubberBtn.classList.remove("active")
    }

    // 细线条
    thinBtn.onclick = () => {
      ctx.globalCompositeOperation = "source-over"
      ctx.lineWidth = 3;
      thinBtn.classList.add("active")
      thinkBtn.classList.remove("active")
      rubberBtn.classList.remove("active")
    }

    // 换颜色
    colorBtn.onchange = (e) => {
      ctx.strokeStyle = e.target.value
    }

    saveBtn.onclick = (e) => {
      // 把img添加到界面
      let urlData = c1.toDataURL()
      // let img = new Image()
      // img.src = urlData;
      // document.body.appendChild(img)

      // 下载img
      var downLoada = document.createElement("a"  )
      downLoada.setAttribute("download", "酷炫签名")
      downLoada.href = urlData;
      downLoada.click()
    }

toDataURL

toDataURL() 方法返回一个包含图片展示的 data URI 。可以使用 type 参数其类型,默认为 PNG 格式。图片的分辨率为 96dpi