来画一个视力检查表吧!

前言

今天要来研究的是 canvas~ 踩下去才发现是一个大坑XD,以下先从最基本的开始认识起,最後再来尝试画出自己的视力检查表/images/emoticon/emoticon37.gif

codepen实作

canvas 基本认识

  • 是 HTML 元素,和<img> 类似,但没有srcalt属性,可透过 JS 操作来绘图
  • 预设尺寸为 300 px × 150 px
  • 只有两个属性:widthheight,没有指定大小就会是上述的预设尺寸
  • 可以用 DOM 操作给予属性
  • 初始状态是透明的,必须透过脚本取得画布再用语法画图
  • canvas 使用的语法参数 x 及 y 都是相对於画布左上角(0,0)位置的距离(对照下图会比较清楚)

codepen

建立画布的方式很简单,就是在 HTML 输入<canvas>标签

<canvas class=".canvas" width="150" height="150"></canvas>

再用操作 DOM 元素方式取得 canvas 元素後,使用getContext方法取得渲染环境,这个方法接受一个参数来指定是几维度的绘图

const canvas = document.querySelector('.canvas'); const ctx = canvas.getContext('2d');

有了基本的设定後就可以来绘制图型了~

绘制矩形

  • 以下三个方式会立即将矩形绘制到画布上
  • ctx.fillRect(x, y, width, height): 绘制填满的矩形
  • ctx.strokeRect(x, y, width, height): 绘制空白矩形
  • ctx.clearRect(x, y, width, height): 清除矩形区域

透过这些语法和更改线条样式的语法就可以画出下面的图样

可以用codepen观察会比较清楚每个方法做到的效果

需要注意的地方是,如果要改变颜色,改变颜色的语法必须在绘制方法前喔!

绘制弧形

ctx.arc(x, y, radius, startAngle, endAngle [, counterclockwise])

弧形的语法需要五个参数,x,y代表圆心在画布上的位置,根据radius为半径画圆,可以利用startAngleendAngle指定开始和结束的位置,counterclockwise是个非必要的参数,接受布林值,预设是 false,代表顺时针绘制,true 则为逆时针绘制

MDN 特别注记: arc()方法用的是弧度(radians)而非角度(degrees),如果要在弧度与角度间换算,需要经过转换,转换的语法如下

radians = (Math.PI/180)* degrees


图片来源:HTML5 Canvas Line Tutorial

小小练习

看着 MDN 示范弧形操作时,联想到了视力检查会出现的C型环,於是有了以下的练习,在开始前先认识一下 C 型视力表的设计

C 型视力表,又名兰氏环形视力表(Landolt C),由瑞士眼科医生Edmund Landolt 於19世纪发明,主要特色为:

  1. 有8个开口方向(E字视力表只有四个方向)
  2. 笔画粗细以及开口大小是直径的五分之一

开始练习~

步骤1: 在 HTML 建立 canvas

<canvas width="400px" height="600px"></canvas>

步骤2: 建立一个可以重复画C型环的函式

  1. 因为笔画粗细和直径是 1:5 的关系,而arc()接受的参数是半径,所以这里有做一下转换
  2. 考量开口的方向会有八个角度,这里的想法是先固定开口距离,再换算开始和结束的角度
function drawC(x, y, lineWidth, gapDirection) {
  const ctx = canvas.getContext('2d');
  ctx.lineWidth = lineWidth;
  const radius = ctx.lineWidth * 2.5;
  const gap = 12;
  const startAngle = (gapDirection + gap) * (Math.PI/180);
  const endAngle =  (gapDirection - gap) * (Math.PI/180);
  
  ctx.beginPath();
  ctx.arc(x,y,radius,startAngle,endAngle);
  ctx.stroke();
}

步骤3: 使用函式画出六排的 C 型环

// 第一排
drawC(100, 80, 20, 180);
drawC(300, 80, 20, 0);

// ...略 (前三排都先直接输入数值)

// 第四排以後
const rotationDegree = 45; 

for (let x = 50; x <= 350; x+= 60) {
  const rotationRatio = Math.floor((Math.random() * 9));
  const direction = 0 + rotationRatio * rotationDegree;
  drawC(x, 320, 4, direction);
}

完成~

结语

每天盯着电脑工作又写铁人赛的大家记得要定期检查视力喔~
/images/emoticon/emoticon41.gif

参考资料:

MDN
Landolt C


<<:  Day29-介接 API(四)Laravel 实作 Dialogflow ES 之 API interactions

>>:  Day29百变红酱-义大利肉酱

冒险村07 - Update gems & js

07 - Update gems & js 专案如果要长久,套件升级是一定是不可或缺的事,从...

Day8 - 布署 GitHub 程序与串接聊天机器人 LINE Messaging API

GitHub 网址:https://github.com/ Heroku 网址:https://w...

爬虫怎麽爬 从零开始的爬虫自学 DAY25 python网路爬虫开爬6-资料储存

前言 各位早安,书接上回我们将程序码改得更方便阅读,还加上抓取连结的功能,今天我们要来把这些抓到的资...

[Day22]Week3总结

在week3里,我们花了两天在学习merkle tree(传送门),看懂了图上的运作流程,也尝试自...

[Day 26] 第二主餐 pt.4-贺乔迁aws二度,aws布署完整步骤

好的,看到标题大家会觉得啊你怎又要乔迁了 没错,由於昨天加前天的尝试 我把原本的aws搞爆了 不过俗...