html绘图环境,Canvas 学习笔记(二):canvas的绘图环境

前面已经了解了canvas元素的一些特性,但是canvas元素在实际使用过程中,仅仅只是充当一个容器,容器内的内容就是canvas的绘图环境了,理解一下就类似于windows的画图里面的“画布”,在前面也知道我们可以在这个绘图环境中“画出”文字“Hello Anker”;

暂时只探讨2D绘图环境,canvas 3D绘图环境被称之为WebGL,是我们下一阶段的目标

Frist of All,既然我们是初学者,还是回忆一下如何获取2D绘图环境。

var canvas = document.getElementById('canvas'),

context = canvas.getContext('2d');

复制代码

如上代码所示,context即为我们下面要学习的Canvas的2D绘图环境。

那么我们先看下绘图环境有哪些属性

(ps:不需要全部看懂,不理解的属性跳过即可):

CanvasRenderingContext2D对象的属性

属性

简介

canvas

指向该绘图环境所属的canvas对象。该属性最常见的用途就是通过它来获取canvas的宽度与高度,分别调用context.canvas.width与context.canvas.height即可

fillstyle

指定该绘图环境在后续图形填充操作中使用的颜色、渐变色或图案

font

设定在调用绘图环境对象的fillText()或者strokeText()方法,所使用的字形状

globalAlpha

全局透明度(取值0~1.0),浏览器会将每个像素的alpha值与该值相乘

globalCompsiteOperation

该值决定了图形绘制时对于重叠的处理方式

lineCap

该值告诉浏览器如何绘制线段的端点(butt/round/square),默认值butt

lineWidth

该值决定了在canvas之中绘制线段的屏幕像素宽度,取值为非负、非无穷double值,默认值1.0

lineJoin

该值决定了两条线段相交时如何绘制交点(bevel/round/miter)默认值miter

miterLimit

如何绘制miter形式的线段交点

shadowBlur

绘制阴影的延伸

shadowColor

绘制阴影的颜色

shadowOffsetX

阴影的水平偏移量

shadowOffsetY

阴影的垂直偏移量

strokeStyle

对于路径描边的样式

textAlign

文本水平对齐的方式

textBaseline

文本垂直对齐的方式

以上属性,除了canvas,其他属性基本为该绘图环境的全局设置,后续在做图像具体绘制(画线,画曲线,文本)的时候再一一介绍各个属性;这里只需要了解到的一点是,CSS只能影响到Canvas元素,无法影响绘图环境(我曾经一度尝试这么做)。

此外在进行绘图操作时,需要频繁的设置这些值。很多时候只是临时的需要改变某些属性(没什么感觉,比如我临时需要在特定时候使用某种字体,绘图完成后又想恢复成通用字体)。

Canvas为context提供了两个ApI叫save()和restore(),用于保存以及恢复当前canvas绘图环境的所有属性。所以上面的需求可以用类似的方法实现:

function drawGrid(font){

context.save(); // 保存所有属性到一个堆栈

context.font = font;

// 绘制需要的图案与文字

context.restore(); // 从堆栈中取出保存的属性,并还原

}

复制代码之所以强调save是压栈,restore是出栈,是因为canvas设计时,是支持save/restore嵌套使用的。

说了这么多,我们来实际使用一下,用canvas做个小小的Anker钟;

3441d7b35ecb8d143cd78dc2238b896d.gif

HTML代码如下

Clock

background: #dddddd;

display: flex;

align-items: center;

justify-content: center;

}

#canvas {

margin: 20px;

background: #ffffff;

border: thin solid #aaaaaa;

}

Canvas not supported

复制代码var canvas = document.getElementById('canvas'),

context = canvas.getContext('2d'),

FONT_HEIGHT = 15,

MARGIN = 35,

HAND_TRUNCATION = canvas.width/25,

HOUR_HAND_TRUNCATION = canvas.width/10,

NUMERAL_SPACING = 20,

RADIUS = canvas.width/2 - MARGIN,

HAND_RADIUS = RADIUS + NUMERAL_SPACING;

function drawCircle(){

context.beginPath();

context.arc(canvas.width/2, canvas.height/2, RADIUS, 0, Math.PI*2, true);

context.stroke();

}

function drawNumerals(){

var numerals = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ],

angle = 0,

numeralWidth = 0;

numerals.forEach(function(numeral){

angle = Math.PI/6 * (numeral-3);

numeralWidth = context.measureText(numeral).width;

context.fillText(numeral,

canvas.width/2 + Math.cos(angle)*(HAND_RADIUS) - numeralWidth/2,

canvas.height/2 + Math.sin(angle)*(HAND_RADIUS) + FONT_HEIGHT/3);

});

}

function drawCenter(){

context.beginPath();

context.arc(canvas.width/2, canvas.height/2, 5, 0, Math.PI*2, true);

context.fill();

}

function drawAnker(){

context.save();

context.beginPath();

context.font = FONT_HEIGHT*3 + 'px Arial';

context.fillStyle = 'cornflowerblue';

context.strokeStyle = 'blue';

context.strokeText("Anker", canvas.width/2 - 55, canvas.height/2 - 50 );

context.fill();

context.restore();

}

function drawHand(loc, isHour){

var angle = (Math.PI*2) * (loc/60) - Math.PI/2,

handRadius = isHour ? RADIUS - HAND_TRUNCATION-HOUR_HAND_TRUNCATION

: RADIUS - HAND_TRUNCATION;

context.moveTo(canvas.width/2, canvas.height/2);

context.lineTo(canvas.width/2 + Math.cos(angle)*handRadius,

canvas.height/2 + Math.sin(angle)*handRadius);

context.stroke();

}

function drawHands(){

var date = new Date,

hour = date.getHours();

hour = hour > 12 ? hour - 12 : hour;

drawHand(hour*5 + (date.getMinutes()/60)*5, true, 0.5);

drawHand(date.getMinutes(), false, 0.5);

drawHand(date.getSeconds(), false, 0.2);

}

function drawClock(){

context.clearRect(0,0,canvas.width,canvas.height);

drawCircle();

drawCenter();

drawAnker();

drawHands();

drawNumerals();

}

context.font = FONT_HEIGHT + 'px Arial';

loop = setInterval(drawClock, 1000);

复制代码

似乎还是挺有意思的不是么?

下一阶段,我们来看下canvas的事件交互是如何做的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值