H5画布 canvas(二)绘制文字、图片、坐标系,canvas颜色和样式,canvas绘制环境

简介: H5画布 canvas(二)绘制文字、图片、坐标系,canvas颜色和样式,canvas绘制环境

1. 绘制文字

ctx.font;设置文本内容的字体属性,使用方式与 css font 相同

ctx.textAlign;设置文本内容的对齐方式

start:默认,文本在指定的位置开始

end:文本在指定的位置结束

center:文本的中心被放置在指定的位置

left:文本左对齐

right:文本右对齐

ctx.textBaseline;设置绘制文本时使用的当前文本基线

alphabetic:默认,文本基线是普通的字母基线

top:文本基线是 em 方框的顶端

hanging:文本基线是悬挂基线

middle:文本基线是 em 方框的正中心

ideographic:文本基线是 em 基线

bottom:文本基线是 em 方框的底端

ctx.fillText();填充文本

ctx.strokeText();绘制文本(无填充)

ctx.measureText();返回包含指定文本宽度的对象


接下来我们在上文饼状图案例的基础上绘制文字:


<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>绘制饼状图&文字</title>
  <style></style>
</head>
<body>
  <div>
    <canvas id="table"></canvas>
  </div>
</body>
<script>
  var canvas = document.getElementById('table'); //获取canvas标签
  var ctx = canvas.getContext('2d'); //获取上下文
  //设置画布宽高、边框(边框也可使用CSS选择器来设定)
  canvas.width = 600;
  canvas.height = 400;
  canvas.style.border = '2px solid #000';
  //定义饼状图数据
  var data = [{
      'value': 0.2,
      'color': '#149985',
      'title': '城市A'
    },
    {
      'value': 0.3,
      'color': 'red',
      'title': '城市B'
    },
    {
      'value': 0.4,
      'color': 'blue',
      'title': '城市C'
    },
    {
      'value': 0.1,
      'color': '#999999',
      'title': '城市D'
    },
  ]
  //绘制饼状图
  var tempAngle = -90; //记录绘制到了哪个角度
  for (var i = 0; i < data.length; i++) {
    ctx.beginPath(); //每一次循环都绘制不同的扇区,所以都要开启新状态
    ctx.moveTo(200, 200); //每一次都回到圆心点开始绘制
    var angle = data[i].value * 360; //每一个扇区的角度
    ctx.fillStyle = data[i].color; //颜色填充按照数据遍历
    var startAngle = tempAngle * Math.PI / 180; //起始角度
    var endAngle = (tempAngle + angle) * Math.PI / 180; //每一次的结束角度=起始角度+扇区角度
    ctx.arc(200, 200, 100, startAngle, endAngle);
    //绘制文字
    var txt = data[i].value * 100 + '%'; //获取要绘制的文字
    var x, y; //文字坐标
    var txtAngle = tempAngle + 1 / 2 * angle; //文字位置的角度 = 起始角度 + 扇区的一半
    //计算文字坐标
    x = 200 + Math.cos(txtAngle * Math.PI / 180) * (100 + 20);
    y = 200 + Math.sin(txtAngle * Math.PI / 180) * (100 + 20);
    ctx.font = '20px "微软雅黑"'; //设置字体
    if (txtAngle > 90 && txtAngle < 270) { //设置y轴左边的文字结束位置对齐,防止文字显示不全
      ctx.textAlign = 'end';
    }
    ctx.fillText(txt, x, y); //填充文字
    ctx.fill();
    tempAngle = tempAngle + angle; //每次绘制完一次扇区起始角度为原角度加该扇区角度
  }
</script>
</html>

加上文字的饼状图如下:

image.png



在这里注意我们计算文字文字位置时用到了两个公式:200 为圆心点的位置,cos 计算 x 轴方向的位置,sin 计算 y 轴方向的位置,100 为半径长度,20 是文字到圆周的距离;该公式通用。


x = 200 + Math.cos(txtAngle * Math.PI / 180) * (100 + 20);
y = 200 + Math.sin(txtAngle * Math.PI / 180) * (100 + 20);

2. 绘制图片(drawImage)

(1)基本绘制方法

ctx.drawImage(img,x,y);绘制图片基本方式,x y 为绘片左上角的坐标, img是绘制图片的dom对象

ctx.drawImage(img,x,y,width,height);绘制图片并规定宽高

ctx.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);绘制图片并在画布上定位被裁剪的部分,sx,sy 裁剪区域的左上角坐标, swidth 裁剪图片的宽度,sheight 裁剪的高度,其余属性相同

如下简单案例:

image.png



(2)案例:序列帧动画(通过图片裁剪,实现人走路的动态效果)

       图片裁剪常用育在一张具有多种元素的图片中裁剪出其中一个元素,例如在一张具有多个人物的图片中抠出其中一个人物等等。接下来我们通过一张人走路的序列帧图来实现动态效果;


原始序列帧图片如下:

image.png



过程也很简单,就是使用到了循环计时器 setInterval,循环裁剪图片中的每一帧,并清除之前裁剪的所有元素,只展示最新的元素,实现动态效果。


<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>序列帧动画</title>
  <style></style>
</head>
<body>
  <div>
    <canvas id="table"></canvas>
  </div>
</body>
<script>
  var canvas = document.getElementById('table'); //获取canvas标签
  var ctx = canvas.getContext('2d'); //获取上下文
  //设置画布宽高、边框(边框也可使用CSS选择器来设定)
  canvas.width = 600;
  canvas.height = 400;
  canvas.style.border = '2px solid #000';
  //绘制图片
  var img = new Image(); //创建图片DOM对象
  img.src = 'img/zoulu.jpg'; //图片路径,设置后img对象会立即加载图片
  img.onload = function () {
    var framIndex = 0;
    setInterval(function () {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      ctx.drawImage(img, framIndex * 80, 0, 50, 400, 200, 100, 80, 300); //绘制图片
      framIndex++; //添加到下一帧
      framIndex %= 5;
    }, 1000 / 6);
  }
</script>
</html>

案例效果如下:

image.png



3. 绘制坐标系

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>绘制坐标系</title>
  <style></style>
</head>
<body>
  <div>
    <canvas id="table"></canvas>
  </div>
</body>
<script>
  var canvas = document.getElementById('table'); //获取canvas标签
  var ctx = canvas.getContext('2d'); //获取上下文
  //设置画布宽高、边框(边框也可使用CSS选择器来设定)
  canvas.width = 600;
  canvas.height = 400;
  canvas.style.border = '2px solid #000';
  //画笔起点
  var x0 = 100;
  var y0 = 380;
  var maxHeight = 390;
  var arrowWidth = 10; //箭头宽度
  //绘制x轴
  ctx.beginPath();
  ctx.strokeStyle = 'blue';
  ctx.moveTo(x0, y0);
  ctx.lineTo(500, 380);
  ctx.lineTo(500 - arrowWidth, 380 - arrowWidth);
  ctx.moveTo(500, 380);
  ctx.lineTo(500 - arrowWidth, 380 + arrowWidth);
  ctx.stroke();
  //绘制y轴
  ctx.beginPath();
  ctx.moveTo(x0, y0);
  ctx.lineTo(100, 0);
  ctx.lineTo(100 - arrowWidth, arrowWidth);
  ctx.moveTo(100, 0);
  ctx.lineTo(100 + arrowWidth, arrowWidth);
  ctx.stroke();
  //绘制线段
  var data = [0.4, 0.5, 0.3, 0.8, 0.4, 0.6]; //假数据
  var pointWidth = 380 / (data.length + 1);
  ctx.beginPath();
  ctx.strokeStyle = 'red';
  for (var i = 0; i < data.length; i++) {
    var x = x0 + (i + 1) * pointWidth;
    var y = y0 - data[i] * maxHeight;
    ctx.lineTo(x, y)
  }
  ctx.stroke();
</script>
</html>

效果如下:

image.png



4. canvas 颜色样式和阴影(了解)

相关颜色样式:


ctx.fillStyle;填充颜色(可支持所有格式的颜色)

ctx.strokeStyle;描边颜色(可支持所有格式的颜色)

ctx.strokeStyle = 'red';
ctx.strokeStyle = '#ccc';
ctx.strokeStyle = 'rgb(255,0,0)';
ctx.strokeStyle = 'rgba(255,0,0,6)';

相关阴影样式(效率低、性能差,建议不使用):


ctx.shadowColor;阴影颜色

ctx.shadowBlur;模糊级别,大于 1 的正整数,数值越高,模糊程度越大

ctx.shadowOffsetX;阴影距形状的水平距离

ctx.shadowOffsetY;阴影距形状的垂直距离

使用方式与 css 中类似:


ctx.shadowColor = 'teal';
ctx.shadowBlur = 10;
ctx.shadowOffsetX = 10;
ctx.shadowOffsetY = 10;
ctx.fillRect(100, 100, 100, 100);

5. 复杂样式

(1)渐变

ctx.createLinearGradient(x0,y0,x1,y1);线性渐变,x0 y0 为起始坐标,x1 y1 为结束坐标,使用时需要添加渐变色

var grd = ctx.createLinearGradient(0, 0, 170, 0);
grd.addColorStop(0, 'black'); //添加一个渐变颜色,值介于 0.0 与 1.0 之间
grd.addColorStop(1, 'white'); //添加一个渐变颜色

ctx.fillStyle = grd; //把渐变设置到填充的样式

ctx.createRadialGradient(x0,y0,r0,x1,y1,r1);圆形渐变,x0 渐变开始圆的 x 坐标,y0 渐变的开始圆的 y 坐标,r0: 开始圆的半径,x1 渐变的结束圆的 x 坐标,y1 渐变的结束圆的 y 坐标,r1 结束圆的半径

var rlg = ctx.createRadialGradient(300, 300, 10, 300, 300, 200);
rlg.addColorStop(0, 'teal'); //添加一个渐变颜色
rlg.addColorStop(0.4, 'navy');
rlg.addColorStop(1, 'purple');

ctx.fillStyle = rlg; //设置 填充样式为延续渐变的样式

ctx.fillRect(100, 100, 500, 500);


(2)绘制背景图

ctx.createPattern(img,repeat);img 设置平铺背景的图片,repeat 背景平铺的方式

var ctx = c.getContext('2d');
var img = document.getElementById('lamp');
var pat = ctx.createPattern(img, 'repeat');
ctx.rect(0, 0, 150, 100);
ctx.fillStyle = pat; //  把背景图设置给填充的样式
ctx.fill();

(3)变换(重点)

ctx.scale(scalewidth,scaleheight);画布缩放

ctx.translate(x,y);位移画布,发生位移后,相当于把画布的 0,0 坐标更换到新的 x,y 位置,所有绘制的新元素都被影响

ctx.rotate(angle);旋转画布


6. 绘制环境的相关操作

ctx.save();保存当前环境的状态,可以把当前绘制环境进行保存到缓存中

ctx.restore();返回之前保存过的路径状态和属性

ctx.globalAlpha=number;设置绘制环境的透明度,值介于0-1之间

ctx.clip();在画布的限定区域绘制,从原始画布中剪切任意形状和尺寸,一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内

canvas.toDataURL(type, encoderOptions);把 canvas 绘制的内容输出成 base64 内容,type 设置输出的类型,比如 image/png image/jpeg 等;encoderOptions 值为 0-1 之间的数字,用于标识输出图片的质量,1 表示无损压缩

var canvas = document.getElementById("canvas");
var dataURL = canvas.toDataURL();
console.log(dataURL);
var img = document.querySelector("#img-demo");//拿到图片的dom对象
img.src = canvas.toDataURL("image/png"); //将画布的内容给图片标签显示

三篇文章速通 canvas:


➡️ 第一部分:canvas介绍,绘制圆形、矩形;

➡️ 第二部分:绘制文字、图片、坐标系,canva颜色和样式,绘制环境;

➡️ 第三部分:canvas库Konva.js的使用。


相关文章
|
存储 缓存 负载均衡
Nginx入门笔记
Nginx入门笔记
573 0
|
开发者
文件蜈蚣,一款免费开源比迅雷还良心的全协议下载神器
说到下载工具,相信很多人都在使用大名鼎鼎的 IDM 下载神器,优点众多:支持多线程下载,支持网页的视频嗅探下载,不过它支持的协议比较少,比如不支持 BT、ed2k、thunder 下载等;
1158 0
文件蜈蚣,一款免费开源比迅雷还良心的全协议下载神器
|
前端开发 JavaScript IDE
Vue3项目搭建规范
Vue3项目搭建规范
502 0
|
Java 关系型数据库 数据库连接
简单易懂的 MyBatis 分库分表方案
本文介绍了一种基于 MyBatis 框架的数据库分库分表方案——shardino。不同于复杂插件方式,该方案通过客户端代码包装实现简便易懂的操作,显式处理分库分表逻辑,确保开发者清晰了解数据分布。项目地址:[https://github.com/pyloque/shardino](https://github.com/pyloque/shardino)。方案中,帖子表按 userId 字段 hash 分为 64 张表,平均分配到多个主从库中,配置文件管理 MySQL 组对象,支持读写分离和权重随机选择从库。代码示例展示了如何计算 partition number 并进行具体操作。
473 22
简单易懂的 MyBatis 分库分表方案
|
前端开发 Java 数据库连接
技术好文共享:电脑睡眠(sleep)和休眠(Hibernate)的区别,以及休眠功能的设置
技术好文共享:电脑睡眠(sleep)和休眠(Hibernate)的区别,以及休眠功能的设置
|
设计模式 算法 Java
23种设计模式,模板方法模式的概念优缺点以及JAVA代码举例
【4月更文挑战第10天】模板方法模式是一种行为设计模式,它定义了一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些特定步骤。
305 0
|
SQL 分布式计算 关系型数据库
实时计算 Flink版产品使用问题之在使用FlinkCDC与PostgreSQL进行集成时,该如何配置参数
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
实时计算 Flink版产品使用问题之在使用FlinkCDC与PostgreSQL进行集成时,该如何配置参数
|
JavaScript 前端开发 编译器
Vue 3:新特性与改进技术详解
【4月更文挑战第25天】Vue 3 提升了编译和运行时性能,引入了Composition API实现灵活代码复用,新增Teleport用于任意位置渲染,支持Fragment多根节点及Suspense处理异步组件。同时,TypeScript支持增强,自定义指令和全局API也得到优化。Vue 3的新特性旨在提供更高效、灵活的开发体验,持续引领前端技术发展。
|
SQL 关系型数据库 MySQL
binlog2sql的安装及使用
binlog2sql的安装及使用
405 2
【Qt 学习笔记】Qt的坐标体系
【Qt 学习笔记】Qt的坐标体系
667 0

热门文章

最新文章