这两天看了HTML5 Canvas基础教程,初步了解了Canvas的基本知识,在这里做一下总结:
Canvas的大致绘画过程很简单:创建canvas标签元素-》创建2D渲染上下文-》画图
$(document).ready(function () {
var canvas = $("#myCanvas");
var context = canvas.get(0).getContext("2d");// 创建2d渲染上下文
// 下面就可以开始画图啦
})
//****************基本图形****************//
// 矩形
context.strokeRect(40, 40, 200, 100);// stroke是边框;fill是填充
// 直线
context.beginPath();
context.moveTo(40, 180);
context.lineTo(240, 180);
context.closePath();
context.stroke();
// 圆形
context.beginPath();
context.arc(230, 90, 50, 0, Math.PI*2, false);//圆心x,圆心y,半径,开始角度,结束角度,true为逆时针
context.closePath();
context.fill();
// 文本
var text = "Hello World";
context.font = "italic 60px serif";
context.strokeText(text, 40, 250);
// 样式
context.fillStyle = "red"; // 填充颜色
context.strokeStyle = "blue"; // 边框颜色
// 通过重置画布宽高可以擦除所有内容,包括样式
canvas.attr("width", canvas.width());
canvas.attr("heigth", canvas.height());
// 使画布填满浏览器窗口
canvas.attr("width", $(window).get(0).innerWidth);
canvas.attr("height", $(window).get(0).innerHeight);
context.fillRect(0, 0, canvas.width(), canvas.height());
// 调整浏览器大小,画布自动调整
$(window).resize(resizeCanvas);
function resizeCanvas() {
canvas.attr("width", $(window).get(0).innerWidth);
canvas.attr("height", $(window).get(0).innerHeight);
context.fillRect(0, 0, canvas.width(), canvas.height());
}
resizeCanvas();
//****************基本图形****************//
//********保存和恢复绘画状态***********//
// 说明:2D渲染上下文会保存一个绘画状态堆栈,其中最新保存的在堆栈顶部,最早的在底部
// 保存绘画状态
context.save();
// 恢复绘图状态
context.restore();
//********保存和恢复绘画状态***********//
//********变形***********//
// 将2D渲染上下文平移
context.translate(150, 0);
context.fillRect(50, 50, 100, 100);
// 缩放
context.scale(2, 2);
context.fillRect(0, 100, 100, 100);
// 旋转:旋转的是2D绘图上下文
context.translate(200, 200);
context.rotate(0.7854);
context.fillRect(-50, -50, 100, 100);
// 变形矩阵
context.save();
context.setTransform(1, 0, 0, 1, 0, 0);
var xScale = Math.cos(0.7854);
var ySkew = -Math.sin(0.7854);
var xSkew = Math.sin(0.7854);
var yScale = Math.cos(0.7854);
var xTrans = 200;
var yTrans = 200;
context.transform(xScale, ySkew, xSkew, yScale, xTrans, yTrans);
context.fillRect(-50, -50, 100, 100);
//********变形***********//
// 全局阿尔法值
context.fillStyle = "blue";
context.fillRect(50, 50, 100, 100);
context.globalAlpha = 0.5; // 阿尔法值
// 合成操作
// source destination
// +over在谁之上;+atop重叠; +in只显示重叠部分; +out只显示不重叠部分;
// lighter将重叠的颜色值相加; copy只绘制源,覆盖掉目标; xor重叠部分变透明
context.globalCompositeOperation = "";
context.fillStyle = "red";
context.fillRect(100, 100, 100, 100);
// 阴影
context.shadowBlur = 20; // 透明度
context.shadowOffsetX = 10; // x位移
context.shadowOffsetY = 10; // y位移
context.shadowColor = "rgb(0, 0, 0)";// 颜色
context.beginPath();
context.arc(100, 300, 50, 0, Math.PI*2, false);
context.closePath();
context.fill();
// 渐变
// 线性渐变
var gradient = context.createLinearGradient(0, 0, 0, canvas.height()); // 起点(x, y),终点(x, y)
gradient.addColorStop(0, "rgb(0,0,0)"); // 起点颜色
gradient.addColorStop(1, "rgb(255,255,255)"); // 终点颜色
context.fillStyle = gradient; // 给予渐变样式
context.fillRect(50, 20, 100, 1000);
// 放射渐变
var gradient = context.createRadialGradient(200, 100, 0, 200, 100, 50); // 起点圆(圆心x,圆心y,半径),终点圆(圆心x,圆心y,半径)
gradient.addColorStop(0, "rgb(0,0,0)"); // 起点颜色
gradient.addColorStop(1, "rgb(255,255,255)"); // 终点颜色
context.fillStyle = gradient;
context.beginPath();
context.arc(200, 100, 50, 0, Math.PI*2, false);
context.closePath();
context.fill();
// 复杂路径
// 三角形
context.restore();
context.beginPath();
context.moveTo(200, 200);
context.lineTo(150, 300);
context.lineTo(250, 300);
context.closePath();
context.fill();
// 贝赛尔曲线
// 二次贝赛尔曲线
context.lineWidth = 5;
context.beginPath();
context.moveTo(150, 400);
context.quadraticCurveTo(250, 350, 400, 400);
context.stroke();
// 三次贝赛尔曲线
context.beginPath();
context.moveTo(150, 600);
context.bezierCurveTo(250, 350, 350, 650, 400, 600);
context.stroke();
// Adobe Illustrator Ai->Canvas插件可以将矢量图转为画布代码
// 导出为图像
var dataURL = canvas.get(0).toDataURL();
var img = $("<img></img>");
img.attr('src', dataURL);
// canvas.replaceWith(img);
// ***********处理图像和视频**************** //
// 访问像素点
var image = new Image();
image.src = "images/test1.jpg";
$(image).load(function(){
// context.drawImage(image, 0, 0, 500, 333);
});
canvas.click(function(e){
var canvasOffset = canvas.offset();
var canvasX = Math.floor(e.pageX - canvasOffset.left);
var canvasY = Math.floor(e.pageY - canvasOffset.top);
/* 因为本地测试用的图片是文件夹内的,也有可能是一个url,js跨域限制是不能获取非同一域名下的数据的,而本地的位置是没有域名的,url是非同一域名的,所以浏览器都认为你是跨域了,才会报错。如果一定要测试这个代码,解决办法也容易,我是直接把文件放到了apache根目录 */
var imageData = context.getImageData(canvasX, canvasY, 1, 1);// imageData有三个属性:width像素区域的宽度;height像素区域的高度;data所访问像素区域的全部像素信息CanvasPixelArray
var pixel = imageData.data;
var pixelColor = "rgba("+pixel[0]+","+pixel[1]+","+pixel[2]+","+pixel[3]+")";
$('body').css("backgroundColor", pixelColor);
});
// 随机绘制像素
var imageData = context.createImageData(200, 200);
var pixels = imageData.data;
var numPixels = imageData.width * imageData.height;
for(var i=0; i<numPixels; i++){
pixels[i*4] = Math.floor(Math.random()*255);
pixels[i*4+1] = Math.floor(Math.random()*255);
pixels[i*4+2] = Math.floor(Math.random()*255);
pixels[i*4+3] = 255;
}
// context.putImageData(imageData, 0, 400);
// 马赛克
var imageData = context.createImageData(500, 500);
var pixels = imageData.data;
// 马赛克块的个数
var numTileRows = 10;
var numTileCols = 10;
// 每一块的尺寸
var titleWidth = imageData.width / numTileCols;
var titleHeight = imageData.height / numTileRows;
for(var r = 0; r < numTileRows; r++){
for(var c = 0; c < numTileCols; c++){
var red = Math.floor(Math.random()*255);
var green = Math.floor(Math.random()*255);
var blue = Math.floor(Math.random()*255);
for(var tr = 0; tr < titleHeight; tr ++){
for(var tc = 0; tc < titleWidth; tc ++){
var trueX = (c*titleWidth)+tc;
var trueY = (r*titleHeight)+tr;
var pos = (trueY*(imageData.width*4)) + (trueX*4);
pixels[pos] = red;
pixels[pos+1] = green;
pixels[pos+2] = blue;
pixels[pos+3] = 255;
}
}
}
}
// context.putImageData(imageData, 0, 0)
canvas.attr("width", canvas.width());
canvas.attr("heigth", canvas.height());
var image = new Image();
image.src = "images/test3.jpg";
$(image).load(function () {
context.drawImage(image, 0, 0);
pixelated();
})
// 翻转颜色
function turnColor () {
var imageData = context.getImageData(0, 0, image.width, image.height);
var pixels = imageData.data;
var numPixels = pixels.length;
context.clearRect(0, 0, canvas.width(), canvas.height());
for(var i=0; i < numPixels; i++){
pixels[i*4] = 255 - pixels[i*4];
pixels[i*4+1] = 255 - pixels[i*4+1];
pixels[i*4+2] = 255 - pixels[i*4+2];
};
context.putImageData(imageData, 0, 0);
}
// 灰度
function grayscale () {
var imageData = context.getImageData(0, 0, image.width, image.height);
var pixels = imageData.data;
var numPixels = pixels.length;
context.clearRect(0, 0, canvas.width(), canvas.height());
for(var i=0; i < numPixels; i++){
var average = (pixels[i*4] + pixels[i*4+1] + pixels[i*4+2])/3;
pixels[i*4] = average;
pixels[i*4+1] = average;
pixels[i*4+2] = average;
};
context.putImageData(imageData, 0, 0);
}
// 像素化
function pixelated () {
var imageData = context.getImageData(0, 0, canvas.width(), canvas.height());
var pixels = imageData.data;
context.clearRect(0, 0, canvas.width(), canvas.height());
// 马赛克块的个数
var numTileRows = 50;
var numTileCols = 50;
// 每一块的尺寸
var titleWidth = image.width / numTileCols;
var titleHeight = image.height / numTileRows;
for(var r = 0; r < numTileRows; r++){
for(var c = 0; c < numTileCols; c++){
var x = (c*titleWidth)+(titleWidth/2);
var y = (r*titleHeight)+(titleHeight/2);
var pos = (Math.floor(y) * (imageData.width*4)) + (Math.floor(x) * 4);
var red = pixels[pos];
var grean = pixels[pos+1];
var blue = pixels[pos+2];
context.fillStyle = "rgb("+red+","+grean+","+blue+")";
// context.fillRect(x-(titleWidth/2), y-(titleHeight/2), titleWidth, titleHeight);
context.beginPath();
context.arc(x, y, titleWidth/2, 0, Math.PI*2, false);
context.closePath();
context.fill();
}
}
}
// ***********处理图像和视频**************** //
// ***********制作动画**************** //
var canvasWidth = canvas.width();
var canvasHeight = canvas.height();
var playAnimation = true;
var startButton = $("#startAnimation");
var stopButton = $("#stopAnimation");
startButton.hide();
// 开始按钮
startButton.click(function() {
$(this).hide();
stopButton.show();
playAnimation = true;
animate();
});
// 结束按钮
stopButton.click(function() {
$(this).hide();
startButton.show();
playAnimation = false;
})
//创建模型
var Shape = function(x, y, width, heigth) {
this.x = x;
this.y = y;
this.width = width;
this.heigth = heigth;
this.radius = Math.random()*100;
this.angle = 0;
}
var shapes = new Array();
// 生成10个对象模型
for(var i=0; i<10; i++){
var x = Math.random()*250;
var y = Math.random()*250;
var width = Math.random()*50;
var heigth = width;
shapes.push(new Shape(x, y, width, heigth));
}
function animate() {
// 1.清除
context.clearRect(0, 0, canvasWidth, canvasHeight);
// 2.绘制
var shapesLength = shapes.length;
for(var i=0; i<shapesLength; i++){
var tmpShape = shapes[i];
// tmpShape.x += Math.random()*4-2;
// tmpShape.y += Math.random()*4-2;
// 圆周运动
var x = tmpShape.x + (tmpShape.radius*Math.cos(tmpShape.angle*(Math.PI/180)));
var y = tmpShape.y + (tmpShape.radius*Math.sin(tmpShape.angle*(Math.PI/180)));
tmpShape.angle += 5;
if(tmpShape.angle > 360){
tmpShape.angle = 0;
}
context.fillRect(x, y, tmpShape.width, tmpShape.heigth);
}
if(playAnimation){
// 3.更新
setTimeout(animate, 33);
}
};
animate();
// ***********制作动画**************** //