四、Canvas基本绘图

Canvas绘图(三)

本章将介绍canvas的以下技巧

  • 填充
  • 创建阴影
  • 画布层面操作

一、填充

本章介绍形状的着色与填充,除此之外,还有渐变

context.fillStyle该属性用于设置画布上形状的基本颜色和填充。该属性支持以下几种方式设置颜色

  • rgb : context.fillStyle = 'rgb(255,0,0)'
  • 十六进制数字字符串 : context.fillStyle = '#66ccff'
  • rgba : context.fillStyle = 'rgba(255,0,0,1)'

A. 线性渐变

线性渐变有3中基本样式 :水平、垂直、对角线

接口 说明
context.createLinearGradient(x1,y1,x2,y2) (x1,y1)和(x2,y2)分别为渐变开始、结束坐标

a. 线性水平渐变

通过沿对象设置的颜色断带你来控制渐变颜色 ,当渐变位置为左上角和右上角时(即y 相同时),就能设置一个水平的渐变,例如 :

drawLinearGradient() {
    // 水平渐变的值必须保持为0
    const gr = this.context.createLinearGradient(100, 100, 200, 100);
    // 添加颜色断点
    gr.addColorStop(0, "rgb(255,0,0)");
    gr.addColorStop(0.5, "rgb(0,255,0)");
    gr.addColorStop(1, "rgb(255,0,0)");
    this.context.fillStyle = gr;
    this.context.fillRect(100, 100, 100, 100);
}
image-20200927173141467.png

还可以将改渐变应用到复杂图形上

drawGradientToComplexShape() {
    const gr = this.context.createLinearGradient(100, 100, 200, 100);
    gr.addColorStop(0, "rgb(255,0,0)");
    gr.addColorStop(0.5, "rgb(0,255,0)");
    gr.addColorStop(1, "rgb(255,0,0)");
    this.context.fillStyle = gr;
    this.context.beginPath();
    this.context.moveTo(100, 100);
    this.context.lineTo(150, 100);
    this.context.lineTo(200, 150);
    this.context.lineTo(150, 200);
    this.context.lineTo(100, 200);
    this.context.lineTo(100, 100);
    this.context.stroke();
    this.context.fill();
    this.context.closePath();
}
image-20200928091944354.png

b. 垂直渐变

垂直渐变的创建方式与水平渐变一样,不同的是,垂直渐变要求x相同,例如

drawGradientToComplexShape() {
    const gr = this.context.createLinearGradient(100, 100, 100, 200);
    gr.addColorStop(0, "rgb(255,0,0)");
    gr.addColorStop(0.5, "rgb(0,255,0)");
    gr.addColorStop(1, "rgb(255,0,0)");
    this.context.fillStyle = gr;
    this.context.beginPath();
    this.context.moveTo(100, 100);
    this.context.lineTo(150, 100);
    this.context.lineTo(200, 150);
    this.context.lineTo(150, 200);
    this.context.lineTo(100, 200);
    this.context.lineTo(100, 100);
    this.context.stroke();
    this.context.fill();
    this.context.closePath();
}
image-20200928092338440.png

另外,我们还可以将垂直渐变应用在描边上

drawGradientToBorder() {
    const gr = this.context.createLinearGradient(100, 100, 100, 200);
    gr.addColorStop(0, "rgb(255,0,0)");
    gr.addColorStop(0.5, "rgb(0,255,0)");
    gr.addColorStop(1, "rgb(255,0,0)");
    this.context.strokeStyle = gr;
    this.context.beginPath();
    this.context.moveTo(100, 100);
    this.context.lineTo(150, 100);
    this.context.lineTo(200, 150);
    this.context.lineTo(150, 200);
    this.context.lineTo(100, 200);
    this.context.stroke();
    this.context.closePath();
}
image-20200928092749924.png

c. 对角线渐变

同理,我们可以轻易的创建对角线的渐变,只要令渐变开始与渐变结束的坐标为右上角和左下角就可以了。

drawGradientDiagonal() {
    const gr = this.context.createLinearGradient(100, 100, 200, 200);
    gr.addColorStop(0, "rgb(255,0,0)");
    gr.addColorStop(0.5, "rgb(0,255,0)");
    gr.addColorStop(1, "rgb(255,0,0)");
    this.context.fillStyle = gr;
    this.context.fillRect(100,100,100,100) 
}
image-20200928093631778.png

B. 径向渐变

径向渐变的定义过程和线性渐变非常类似,他需要6个参数设置,而线性渐变仅仅需要4个,它同样采用颜色断点来创建颜色变化

接口 说明
context.createRadiaGradient(x1,y1,r1,x2,y2,r2) 分别定义圆心与半径,分为两个点,第一个圆是开始圆,第二个圆是结束圆

例如画一个简单的径向渐变

drawRadialGradient() { 
    const gr = this.context.createRadialGradient(150, 150,25, 150, 150,100);
    gr.addColorStop(0, "rgb(255,0,0)");
    gr.addColorStop(0.5, "rgb(0,255,0)");
    gr.addColorStop(1, "rgb(255,0,0)");
    this.context.fillStyle = gr;
    this.context.fillRect(100,100,100,100) 
}
image-20200928095933623.png

写一个复杂的线性渐变

drawRadialGradient() {
    const gr = this.context.createRadialGradient(125, 125, 10, 150, 150, 50);
    gr.addColorStop(0, "rgb(255,0,0)");
    gr.addColorStop(0.5, "rgb(0,255,0)");
    gr.addColorStop(1, "rgb(255,0,0)");
    this.context.fillStyle = gr;
    this.context.arc(150, 150 , 50, 0, (Math.PI / 180) * 360, false);
    this.context.fill()
}
image-20200928100323178.png

C. 用图案填充形

接口 说明
createPattern(image,mode) 填充图案初始化,它有两个参数,第一个是Image对象实例;第二个是String类型,表示在形状中如何显示repeat

有以下几种填充类型 :

  • repeat
  • repeat-x
  • repeat-y
  • no-repeat

现代浏览器对这4中类型的支持度不同,不过,普遍都能支持标准的repeat类型。

例如,填充以下图案 :

drawFillImage() {
    const fillImage = new Image();
    fillImage.onload = () => {
    const fillPattern = this.context.createPattern(fillImage, "repeat");
    this.context.fillStyle = fillPattern;
    this.context.fillRect(0, 0, 400, 400);
    };
    fillImage.src = helloworld;
}
image-20200928111941561.png

二、创建阴影

可以通过以下几个属性为对象添加阴影

属性名 说明
shadowOffsetX x偏移值
shadowOffsetY y偏移值
shadowColor 阴影颜色
shadowBlur 阴影模糊效果的程度,即模糊级数

例如 :

drawShadow() {
    this.context.fillStyle = "red";
    this.context.shadowOffsetX = 4;
    this.context.shadowOffsetY = 4;
    this.context.shadowColor = "black";
    this.context.shadowBlur = 10
    this.context.fillRect(10, 10, 100, 100);
}
image-20200928142311184.png

三、画布层面操作

A. 简单填充

使用一个新的背景色简单的填充整个画布

drawAllCanvas() { 
    this.context.fillStyle = '#66ccff'
    this.context.fillRect(0,0,this.theCanvas.width,this.theCanvas.height)
}

B. 重置画布的宽和高

当画布的宽或者高被重置时,当前画布的内容就会被移除

clearRect() {
    const w = this.theCanvas.width;
    const h = this.theCanvas.height;
    this.theCanvas.width = w;
    this.theCanvas.width = h;
}

C. 检查一个点是否在当前路径中

可以使用isPointInPath检查一个点是否在当前路径

isInThePath() {
    this.context.strokeStyle = "red";
    this.context.lineWidth = 5;
    this.context.moveTo(0, 0);
    this.context.lineTo(50, 0);
    this.context.lineTo(50, 50);
    this.context.stroke();
    console.log(this.context.isPointInPath(50, 1));
    this.context.closePath();
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,924评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,781评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,813评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,264评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,273评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,383评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,800评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,482评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,673评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,497评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,545评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,240评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,802评论 3 304
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,866评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,101评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,673评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,245评论 2 341