HTML绘图(一):<canvas>

1.Canvas简介

<canvas>是HTML5新增的,可以使用JS绘制图像的HTML元素。由HTML配合height和width属性,JS进行图像绘制

2.基本使用
<canvas id="tutorial" width="300" height="300"></canvas>
2.1 元素

<canvas> 只有两个可选的属性 width(默认为300px)和heigth (默认150px),而没有 src、alt 属性。

  • 注意: ① 不要用css属性来设置<canvas>的宽高,避免其与初始比例不一致而产生的扭曲。 ②
    由于<canvas>是HTML5新增标签,部分浏览器不支持显示该元素,当浏览器不支持<canvas>渲染时,需要显示替代内容;支持时则会忽略其中的替代内容。
<!--文本替换-->
<canvas>
    你的浏览器不支持 canvas,请升级你的浏览器。
</canvas>

<!--<img>替换-->
<canvas>
    <img src="./美女.jpg" alt=""> 
</canvas>
2.2 渲染上下文
var canvas = document.getElementById('tutorial');
//获得 2d 上下文对象
var ctx = canvas.getContext('2d');

当不支持时,填充替代内容

var canvas = document.getElementById('tutorial');

if (canvas.getContext){
  var ctx = canvas.getContext('2d');
  // drawing code here
} else {
  // canvas-unsupported code here
}
3. 形状绘制
3.1 坐标空间

如下图所示,canvas 元素默认被网格所覆盖。通常来说网格中的一个单元相当于 canvas 元素中的一像素。栅格的起点为左上角,坐标为 (0,0) 。所有元素的位置都相对于原点来定位。
栅格(grid)

3.2 绘制矩形

<canvas>只支持一种原生的图形绘制:矩形。
canvas 提供了三种方法绘制矩形(默认颜色为黑色):

  • fillRect(x, y, width, height):绘制一个填充的矩形。
  • strokeRect(x, y, width, height):绘制一个矩形的边框。
  • clearRect(x, y, widh, height):清除指定的矩形区域,然后这块区域会变的完全透明。
4. 绘制路径(path)

步骤:1. 创建路径起始点
2.调用绘制方法去绘制出路径
3.把路径封闭
4.一旦路径生成,通过描边或填充路径区域来渲染图形。

beginPath()
#新建一条路径,路径一旦创建成功,图形绘制命令被指向到路径上生成路径

moveTo(x, y)
#把画笔移动到指定的坐标(x, y)。相当于设置路径的起始点坐标。

closePath()
#闭合路径之后,图形绘制命令又重新指向到上下文中

stroke()
#通过线条来绘制图形轮廓

fill()
#通过填充路径的内容区域生成实心的图形
#填充三角形
function draw(){
    var canvas = document.getElementById('tutorial');
    if (!canvas.getContext) return;
    var ctx = canvas.getContext("2d");
    ctx.beginPath();
    ctx.moveTo(50, 50);
    ctx.lineTo(200, 50);
    ctx.lineTo(200, 200);
   
    ctx.fill(); //填充闭合区域。如果path没有闭合,则fill()会自动闭合路径。
}
draw();
5.绘制动画

动画的基本步骤

  1. 清空 。canvas 再绘制每一帧动画之前,需要清空所有。清空所有最简单的做法就是 clearRect() 方法。
  2. 保存 canvas 状态 。如果在绘制的过程中会更改 canvas 的状态(颜色、移动了坐标原点等),又在绘制每一帧时都是原始状态的话,需要保存canvas的状态。
  3. 绘制动画图形这一步才是真正的绘制动画帧。
  4. 恢复 canvas 状态。如果你前面保存了 canvas 状态,则应该在绘制完成一帧之后恢复 canvas 状态。
5.1 控制动画

为了执行动画,我们需要一些可以定时执行重绘的方法。一般用到下面三个方法(这三个方法都属于浏览器的window对象的方法):

  1. setInterval(code,millisec[,"lang"]) 方法可按照指定的周期(以毫秒计)来调用函数或计算表达式,实现定时周期执行
    clearInterval()取消setInterval()设置的定时器
<script>
    function fun() {
        document.write("定时器"+"<br>")
    }
    //间隔200ms周期性调用函数fun
    setInterval("fun()",200);
</script>
  1. setTimeout(code, millisec) 方法用于在指定的毫秒数后调用函数或计算表达式,实现倒计时。(setTimeout() 只执行 code 一次。如果要多次调用,请使用 setInterval() 或者让 code 自身再次调用 setTimeout()
    clearTimeout()取消setTimeout()设置的定时器。
<script>
        function fun() {
            alert("定时器")
        }
        //2000ms,也就是2s后执行fun1函数
        setTimeout("fun()",2000);
</script>
  1. requestAnimationFrame()
<script>
    let S = 0;
    function fun() {
        document.write("定时器"+"<br>");
//        发起下一次fun执行请求
        requestAnimationFrame(fun);
        S++;
    }
//    开启函数fun第一次执行
    fun();
</script>
5.2 Demo

**示例1:**实现一个无穷循环的计时

<html>
<head>
<script type="text/javascript">
var c=0
var t
function timedCount()
{
document.getElementById('txt').value=c
c=c+1
t=setTimeout("timedCount()",1000)
}

function stopCount()
{
clearTimeout(t)
}
</script>
</head>

<body>
<form>
<input type="button" value="开始计时!" onClick="timedCount()">
<input type="text" id="txt">
<input type="button" value="停止计时!" onClick="stopCount()">
</form>

<p>
请点击上面的“开始计时”按钮。输入框会从 0 开始一直进行计时。点击“停止计时”可停止计时。
</p>

</body>

</html>

**示例2:**一个简单的数字时钟

<html>
<head>
<script type="text/javascript">
function startTime()
{
var today=new Date()
var h=today.getHours()
var m=today.getMinutes()
var s=today.getSeconds()
// add a zero in front of numbers<10
m=checkTime(m)
s=checkTime(s)
document.getElementById('txt').innerHTML=h+":"+m+":"+s
t=setTimeout('startTime()',500)
}

function checkTime(i)
{
if (i<10) 
  {i="0" + i}
  return i
}
</script>
</head>

<body onload="startTime()">
<div id="txt"></div>
</body>
</html>

**示例3:**一个简单的时钟表盘

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
<style>
	body {
		padding: 0;
		margin: 0;
		background-color: rgba(0, 0, 0, 0.1)
	}

	canvas {
		display: block;
		margin: 200px auto;
	}
</style>
</head>
<body>
<canvas id="solar" width="300" height="300"></canvas>
<script>
init();

function init(){
    let canvas = document.querySelector("#solar");
    let ctx = canvas.getContext("2d");
    draw(ctx);
}

function draw(ctx){
    requestAnimationFrame(function step(){
        drawDial(ctx); //绘制表盘
        drawAllHands(ctx); //绘制时分秒针
        requestAnimationFrame(step);
    });
}
/*绘制时分秒针*/
function drawAllHands(ctx){
    let time = new Date();

    let s = time.getSeconds();
    let m = time.getMinutes();
    let h = time.getHours();

    let pi = Math.PI;
    let secondAngle = pi / 180 * 6 * s;  //计算出来s针的弧度
    let minuteAngle = pi / 180 * 6 * m + secondAngle / 60;  //计算出来分针的弧度
    let hourAngle = pi / 180 * 30 * h + minuteAngle / 12;  //计算出来时针的弧度

    drawHand(hourAngle, 60, 6, "red", ctx);  //绘制时针
    drawHand(minuteAngle, 106, 4, "green", ctx);  //绘制分针
    drawHand(secondAngle, 129, 2, "blue", ctx);  //绘制秒针
}
/*绘制时针、或分针、或秒针
 * 参数1:要绘制的针的角度
 * 参数2:要绘制的针的长度
 * 参数3:要绘制的针的宽度
 * 参数4:要绘制的针的颜色
 * 参数4:ctx
 * */
function drawHand(angle, len, width, color, ctx){
    ctx.save();
    ctx.translate(150, 150); //把坐标轴的远点平移到原来的中心
    ctx.rotate(-Math.PI / 2 + angle);  //旋转坐标轴。 x轴就是针的角度
    ctx.beginPath();
    ctx.moveTo(-4, 0);
    ctx.lineTo(len, 0);  // 沿着x轴绘制针
    ctx.lineWidth = width;
    ctx.strokeStyle = color;
    ctx.lineCap = "round";
    ctx.stroke();
    ctx.closePath();
    ctx.restore();
}

/*绘制表盘*/
function drawDial(ctx){
    let pi = Math.PI;

    ctx.clearRect(0, 0, 300, 300); //清除所有内容
    ctx.save();

    ctx.translate(150, 150); //一定坐标原点到原来的中心
    ctx.beginPath();
    ctx.arc(0, 0, 148, 0, 2 * pi); //绘制圆周
    ctx.stroke();
    ctx.closePath();

    for (let i = 0; i < 60; i++){//绘制刻度。
        ctx.save();
        ctx.rotate(-pi / 2 + i * pi / 30);  //旋转坐标轴。坐标轴x的正方形从 向上开始算起
        ctx.beginPath();
        ctx.moveTo(110, 0);
        ctx.lineTo(140, 0);
        ctx.lineWidth = i % 5 ? 2 : 4;
        ctx.strokeStyle = i % 5 ? "blue" : "red";
        ctx.stroke();
        ctx.closePath();
        ctx.restore();
    }
    ctx.restore();
}
</script>
</body>
</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值