一、基础
canvas标签,设置画布宽高及浏览器不支持canvas时提示信息。
<canvas id="drawing" width="1000" height="600">your browser not hold cnavas.</canvas>
<script>
var drawing = document.querySelector("#drawing");
drawing.style.border = "1px solid #000";
if (drawing.getContext){
var context = drawing.getContext("2d");
context.fillStyle = "orange"; // 填充样式
context.strokeStyle = "red"; // 描边样式
// 矩形
context.fillRect(10, 10, 80, 80);
context.strokeRect(100, 10, 80, 80);
context.clearRect(30, 30, 20, 20);
// 路径
context.beginPath();
// 圆弧
context.arc(60, 150, 50, 0, 2*Math.PI, false); // Ox, Oy, radius, startA, endA, dire
// 弧线
context.arcTo(170, 150, 210, 180, 150); // Ox, Oy, Nx, Ny, radius
// 直线
context.lineTo(260, 230); // Nx, Ny
// 矩形线
context.rect(10, 300, 50, 50);
// 闭合路劲
context.closePath();
context.stroke(); // 描边
context.fill(); // 填充
// 文本
context.font = "bold 16px Arial";
context.textAlign = "start";
context.textBaseline = "top";
context.fillText("text", 300, 10);
}
</script>
二、划分区域
类似于绘制坐标图
<script>
var drawing = document.querySelector("#drawing");
if (drawing.getContext){
var context = drawing.getContext("2d");
context.strokeStyle = "#000";
context.lineWidth = 1;
context.beginPath();
context.font = "14px";
context.textBaseline = "middle";
drawLine(context, 0);
context.textAlign = "center";
context.textBaseline = "top";
drawLine(context, 1);
context.stroke();
}
function drawLine(context, mode) {
// Horizontal
if (mode == 0){
for(var i=0;i<6;i++){
context.moveTo(0, 100*(i+1));
context.lineTo(1000, 100*(i+1));
context.fillText(100*(i+1)+"px", 0, 100*(i+1));
}
}else if(mode == 1){
for(var i=0;i<9;i++){
context.moveTo(100*(i+1), 0);
context.lineTo(100*(i+1), 700);
context.fillText(100*(i+1)+"px", 100*(i+1), 0);
}
}
}
</script>
效果如下:
三、图像绘制
图像的绘制,阴影、渐变的使用
<script>
var drawing = document.getElementById("drawing");
var image = document.getElementsByTagName("img")[0];
if(drawing.getContext){
var context = drawing.getContext("2d");
context.drawImage(image, 10, 10, 200, 150); // image, posX, posY, contextWit, contextHei
// image, imageX, imageY, imageWid, imageHei, posX, posY, contextWit, contextHei
context.drawImage(image, 0, 0, 1920, 1080, 10, 170, 400, 300);
// 阴影
context.shadowColor = "#000";
context.shadowOffsetX = 0;
context.shadowOffsetY = 0;
context.shadowBlur = 50;
context.fillStyle = "orange";
context.fillRect(400, 10, 100, 100);
// 渐变
// startX, startY, endX, endY
var gradient = context.createLinearGradient(500, 150, 600, 250);
gradient.addColorStop(0, "#fff");
gradient.addColorStop(1, "#000");
context.fillStyle = gradient;
context.fillRect(500, 150, 100, 100);
// startOX, startOY, startRadius, endOX, endOY, endRadius
gradient = context.createRadialGradient(700, 350, 0, 700, 350, 100);
gradient.addColorStop(0, "#fff");
gradient.addColorStop(1, "#000");
context.fillStyle = gradient;
context.beginPath();
context.arc(700, 350, 100, 0, 2*Math.PI);
context.fill();
}
</script>
效果如下:
四、case
1.动态实时时钟
<script>
var drawing = document.getElementById("drawing");
if(drawing.getContext){
var context = drawing.getContext("2d");
context.strokeStyle = "#000";
context.font = "bold 18px Arial";
context.textAlign = "center";
context.textBaseline = "middle";
context.translate(270, 270); // 移动原点
showClock(context);
setInterval(function () {
context.clearRect(-270, -270, 1000, 700);
showClock(context);
}, 1000)
}
function showClock(context) {
context.beginPath();
context.arc(0, 0, 258, 0, 2*Math.PI); // 外圆半径258
context.moveTo(250, 0);
context.arc(0, 0, 250, 0, 2*Math.PI); // 内圆半径250
drawMoment(context);
computePointer(context, 0);
computePointer(context, 1);
computePointer(context, 2);
context.stroke();
}
function drawMoment(context) {
var posX, posY, markEndX, markEndY, posDeg;
for(var i=0;i<12;i++){
posDeg = i*360/12;
posX = Math.sin(posDeg*Math.PI/180)*230; // 时刻文字距圆心距离230
posY = Math.cos(posDeg*Math.PI/180)*-230;
if(i === 0){
context.fillText("12", posX, posY);
}else{
context.fillText(i.toString(), posX, posY);
}
}
for(var j=0;j<60;j++){
posDeg = j*360/60;
posX = Math.sin(posDeg*Math.PI/180)*250;
posY = Math.cos(posDeg*Math.PI/180)*-250;
markEndX = Math.cos((posDeg+270)*Math.PI/180)*(250-4); // 普通时刻标记线长4
markEndY = Math.sin((posDeg+270)*Math.PI/180)*(250-4);
if(parseInt(j/5) === j/5){
markEndX = Math.cos((posDeg+270)*Math.PI/180)*(250-9); // 整点时刻标记线长9
markEndY = Math.sin((posDeg+270)*Math.PI/180)*(250-9);
}
context.moveTo(posX, posY);
context.lineTo(markEndX, markEndY);
}
}
function computePointer(context, mode) {
var myDate = new Date();
var hourPointerLen = 150, // 时针长
minutePointerLen = 180, // 分针长
secondPointerLen = 220; // 秒针长
// 以3点方向为0的方位角,下同
var secondDeg = myDate.getSeconds()*360/60 + 270,
minuteDeg = myDate.getMinutes()*360/60 + (secondDeg-270)/60 + 270,
hourDeg = myDate.getHours()*360/12 + (minuteDeg-270)/12 + 270;
if(mode === 0){
// 时针
drawPointer(context, hourDeg, hourPointerLen);
}else if(mode === 1){
// 分针
drawPointer(context, minuteDeg, minutePointerLen);
}else if(mode === 2){
// 秒针
drawPointer(context, secondDeg, secondPointerLen);
}
}
function drawPointer(context, dge, len) {
var posX = Math.cos(dge*Math.PI/180)*len;
var posY = Math.sin(dge*Math.PI/180)*len;
var mark1X = posX + Math.cos((dge-135)*Math.PI/180)*10; // 以3点方向为0的方位角,下同
var mark1Y = posY + Math.sin((dge-135)*Math.PI/180)*10; // 指针箭头部分长10
var mark2X = posX + Math.cos((dge-225)*Math.PI/180)*10;
var mark2Y = posY + Math.sin((dge-225)*Math.PI/180)*10;
context.moveTo(0, 0);
context.lineTo(posX, posY);
context.lineTo(mark1X, mark1Y);
context.moveTo(posX, posY);
context.lineTo(mark2X, mark2Y);
}
</script>
效果图如下:
2.图像灰阶处理
<script>
var drawing = document.getElementById("drawing");
var pic = document.getElementsByTagName("img")[0];
if (drawing.getContext){
var context = drawing.getContext("2d");
context.drawImage(pic, 10, 10, 400, 300);
var imageData = context.getImageData(10, 10, 400, 300);
console.log(imageData.width + "---" + imageData.height);
var data = imageData.data;
// data为数组,依次为各像素点红、绿、蓝、透明度值
for(var i=0, len=data.length;i< len;i += 4){
var red = data[i],
green = data[i+1],
blue = data[i+2],
alpha = data[i+3];
aveValue = Math.floor((red + green + blue)/3);
data[i] = data[i+1] = data[i+2] = aveValue;
}
imageData.data = data;
context.putImageData(imageData, 10, 10);
}
</script>
效果如下:
原理:通过getImageDate()函数获取到图像的数据,返回一个包含三个元素的数组,分别为图像宽、高及图像源数据列表。源数据列表的元素依次为图像每个像素的红、绿、蓝原色及透明度,正是每个元素的三原色以及透明度共同构成了彩色的图像。然后将三原色求平均值,并使每个像素的三原色都为该平均值,而透明度不变,最后呈现出的图像就是灰色的(三原色相等为灰色,不同值构成了图像)。