`
hiuman
  • 浏览: 52491 次
  • 性别: Icon_minigender_2
  • 来自: 广州
社区版块
存档分类
最新评论

canvas的用法

阅读更多
包括:
介绍。
基础入门。(兼容性。获取canvas上下文。绘制直线/描边,填充内容。绘制表格。)
canvas是基于状态的绘图。
绘制矩形。
绘制圆形。
绘制文本。
绘制图片。
阴影。
渐变。
绘制背景图。
变换。



介绍:
HTML5的新标签<canvas></canvas>

canvas标签通过JavaScript在网页上绘制图像,本身不具备绘图功能。
canvas拥有多种绘制路径,矩形,圆形,字符以及添加图像的方法。

canvas可以做游戏,图表,广告等等。

基础入门。
设置canvas的宽和高是通过canvas标签的属性来设置,不要用css设置。
<canvas id="canvas" width="400" height="400"></canvas>

还可以在JS中通过属性指定。
var canvas = document.getElementById('canvas');  //获取canvas标签
canvas.width=400;
canvas.height=400;


兼容性。
当浏览器不支持canvas时,在canvas标签内编写提示文字。

<canvas>你的浏览器不支持canvas,请更换浏览器后再试。</canvas>

(当浏览器支持canvas时,canvas会执行相关JS代码)

获取canvas上下文。
canvas上下文就是绘制工具的集合。

写在canvas标签后,或者window.onload = function(){}

var canvas = document.getElementById('canvas');  //获取canvas标签
var ctx= canvas.getContext('2d');  //获取canvas的上下文  3D=>'webgl'


得到canvas上下文后就可以开始绘制了。
canvas的坐标系和浏览器的坐标系一致。都是左上角为(0,0)。

绘制直线/描边,填充内容。
ctx.moveTo(100,100);  //画笔移动到(100,100)
ctx.lineTo(200,100);  //画一条直线到(200,100)
ctx.lineTo(100,200);  //画一条直线到(100,200)
//到此为止,只绘制了路径,还没描线。

ctx.stroke();  //描线。



将路径闭合。
ctx.moveTo(100,100);  //画笔移动到(100,100)
ctx.lineTo(200,100);  //画一条直线到(200,100)
ctx.lineTo(100,200);  //画一条直线到(100,200)

ctx.lineTo(100,100);  //画一条直线到(100,100)

ctx.stroke();  //描线。


还可以使用ctx.closePath()来闭合路径。
ctx.moveTo(100,100);  //画笔移动到(100,100)
//必须要写moveTo(),否则画笔没有位置。
//没有写moveTo()直接写lineTo()的话,画笔的位置直接到lineTo()的位置,相当于moveTo()

ctx.lineTo(200,100);  //画一条直线到(200,100)
ctx.lineTo(100,200);  //画一条直线到(100,200)

ctx.closePath()  //闭合路径

ctx.stroke();  //描线。

都是一样的效果:


修改描边的样式。在stroke()描边之前设置描边样式。
ctx.lineWidth = 4;  //线宽
ctx.strokeStyle = 'red';  //颜色



填充内容。默认是黑色。修改填充的样式。
ctx.fill();
ctx.fillStyle = 'blue';  //颜色



问题:填充后,为什么描边变细?
答案:描边是2像素在里面2像素在外边。填充后,里面的2像素被遮盖住了。


绘制表格。
var rectH = 10;  //行高
var rectW = 10;  //列宽
//绘制横线:
for(var i = 0;i< canvas.width / rectH;i++){
	ctx.moveTo(0,i*rectH);
	ctx.lineTo(canvas.width,i*rectH);
	//绘制竖线
	for(var j = 0;j<canvas.height / rectW;j++){
		ctx.moveTo(j*rectW,0);
		ctx.lineTo(j*rectW,canvas.height);
	}
}
ctx.lineWidth = 0.5;
ctx.strokeStyle = '#ccc';
ctx.stroke();


在这基础上就可以绘制折线图了。

绘制箭头的思路:

绘制数据的思路:


var x0 = 100,y0 = 500;
var maxHeight = 300;
var arrowWidth = 10;// 箭头宽度

// 绘制x轴
ctx.beginPath();
ctx.strokeStyle = "blue";
ctx.moveTo(x0, y0);
ctx.lineTo(500, 500);

// 箭头
ctx.lineTo(500-arrowWidth, 500-arrowWidth);
ctx.moveTo(500, 500);
ctx.lineTo(500-arrowWidth, 500+arrowWidth);
ctx.stroke();

//绘制y轴
ctx.beginPath();
ctx.strokeStyle = "purple";
ctx.moveTo(x0, y0);
ctx.lineTo(100, 100);

// 箭头
ctx.lineTo(100-arrowWidth, 100+arrowWidth);
ctx.moveTo(100, 100);
ctx.lineTo(100+arrowWidth, 100+arrowWidth);
ctx.stroke();

// 绘制线段
var data = [.4 ,.5 ,.8 ,.7];
var pointWidth = 400 / (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();





canvas是基于状态的绘图。
比如绘制两条不同颜色的直线。
ctx.strokeStyle = 'red';
ctx.lineWidth=5;

//第一条线
ctx.moveTo(100,100);
ctx.lineTo(300,100);
ctx.stroke();

//第二条线
ctx.strokeStyle = 'blue';
ctx.moveTo(100,200);
ctx.lineTo(300,200);
ctx.stroke();




问题:两条线颜色为什么一样?
解决方法:canvas是基于状态的绘图。设置ctx.beginPath()即可。


//第二条线
ctx.beginPath();

ctx.strokeStyle = 'blue';
ctx.moveTo(100,200);
ctx.lineTo(300,200);
ctx.stroke();




beginPath()相当于开启新状态。

绘制第一条线的时候也可以beginPath(),默认一开始就有状态。
绘制第二条线的新状态,可以继承之前的状态的样式,但是当前的状态设置的所有样式,只能作用于当前的状态。

绘制矩形。
绘制矩形:ctx.rect(x,y,w,h);  //左上角坐标(x,y),w宽,h高。

ctx.rect(50,50,50,50);
ctx.stroke();

ctx.strokeRect(120,120,50,50);  //和上面写法的效果一致。

ctx.fillRect(190,190,50,50);  //如果是fill(填充),会自动闭合路径。




清除矩形:相当于橡皮擦。
ctx.clearRect(x,y,w,h);

ctx.clearRect(195,195,30,30);




绘制圆形。
ctx.arc(x,y,r,startAngle,endAngle,counterclockwise); 
//圆心坐标(x,y),半径r,开始弧度,结束弧度,顺时针/逆时针(默认顺时针如图)




换算公式:rad = deg*Math.PI/180;

绘制0-30°的圆弧。
ctx.arc(100,100,100,0,30*Math.PI/180,false);




加上closePath()会闭合路径。



如果要连接到圆心点。先moveTo(圆心点)即可。
ctx.moveTo(100,100)
ctx.arc(100,100,100,0,30*Math.PI/180,false);
ctx.closePath();
ctx.stroke();




绘制饼状图的其中一个扇形。
ctx.moveTo(200,200);
ctx.fillStyle = 'red'
ctx.arc(200,200,100,-90*Math.PI/180,-30*Math.PI/180,false);
ctx.fill()




假设有这样一个JSON数据。
var data =[{
"value":.2,
"color":"red",
"title":"应届生"
},{
"value":.3,
"color":"blue",
"title":"社会招生"
},{
"value":.4,
"color":"green",
"title":"推荐"
},{
"value":.1,
"color":"yellow",
"title":"公开课"
}];


将数据变成饼状图。
value代表占比。从-90°开始绘制。

//先画扇形。
var tempAngle = -90;  //从-90度开始
var x0 = 150,y0 = 150,radius = 100;  //圆心和半径
for(var i=0;i<data.length;i++){
	ctx.beginPath();
	ctx.moveTo(x0,y0);  //圆心
	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(x0,y0,radius,startAngle,endAngle)
	ctx.fill();

	tempAngle+=angle;
}




绘制文本。
ctx.strokeText('hello',450,400); //文字,坐标
ctx.fillText('hello',150,100);

ctx.moveTo(300,300);
ctx.fillStyle = 'purple';
ctx.font = '20px 微软雅黑';
ctx.textBaseline = "bottom";  //基线
ctx.textAlign = "left";
// ctx.strokeText('hello',450,400);  //空心文字
ctx.fillText('hello',100,300);  //实体填充文字



行高行距的概念:


对齐方式:


饼状图的文字。假设,在角度的一半绘制一条直线出来,写上XX%,思路如图。



绘制完饼状图后,fill前。绘制文字。
// 绘制文字
	var txt = data[i].value * 100 +'%';
	var x,y;
	var textAngle = tempAngle + 1/2 *angle;
	x=x0+Math.cos(textAngle * Math.PI / 180) * (radius + 20);
	y=y0+Math.sin(textAngle * Math.PI / 180) * (radius + 20);

// 左侧文字太长会越过饼状图。
	if(textAngle>90&&textAngle<270){
		ctx.textAlign = "end"
	}

	ctx.fillText(txt,x,y);


文字会超过:

文字不会超过:


ctx.measureText()  //measure测量;返回文本的宽度



绘制图片:

ctx.drawImage(img,x,y);  //img是图片的DOM对象。  绘制的坐标。


// 创建图片的dom对象
var img = new Image();
img.src='img.jpg';  //只要设置了src属性,当前img对象立即去加载图片。

img.onload = function(){
	// 图片加载完成后,绘制图片
	ctx.drawImage(img,100,100);
}


以上的img和以下的方法获得的img是一样的,都是dom对象。

var img2 = document.getElementById('imagedemo');




恶搞✧(≖ ◡ ≖✿)
for(var i=0;i<10;i++){
	ctx.drawImage(img,100+i*10,100+i*10);
}




还可以设置宽高,不设置的时候是图片的默认宽高。
ctx.drawImage(img,x,y,w,h);  //w,h,宽高。


ctx.drawImage(img,100,100,50,50);


被拉伸:


如果要保持宽高比,则 原来的高度 / 原来的宽度 = 绘制的高度 / 绘制的宽度 。
假设已知绘制的宽度,则绘制的高度为 原来的高度*绘制的宽度/原来的宽度。
var ow = img.width;
var oh = img.height;
ctx.drawImage(img,100,100,200,200*oh/ow);




绘制图片裁剪区域。
ctx.drawImage(img,sx,sy,sw,sh,x,y,w,h)  //截取的坐标。截取的宽高。绘制的坐标。绘制的宽高。


比如:网上找的一张图:截取出第一个人物:


ctx.drawImage(img,195,26,276,377,100,100,200,300);



逐帧动画/序列帧动画:定时器。


先做第一行的动作。
var frameIndex = 0; //帧数
setInterval(function(){
	// 清除之前的内容
	ctx.clearRect(0, 0, canvas.width, canvas.height);
	// 如果通过代码重新设置canvas画布的宽高,canvas画布里的所有内容都被清空。(不建议使用)
	//canvas.width = canvas.width;
	ctx.drawImage(
		img,
		frameIndex*53.25,  //截取的坐标
		0,  //截取的坐标
		53.25,  //截取的宽
		92.75,  //截取的高
		200,  //绘制的坐标
		200,  //绘制的坐标
		53.25*2,  //绘制的宽
		92.75*2  //绘制的高
		)
	frameIndex++;
	frameIndex%=4;  //取余  4%4=0
},1000/10);  //1秒10帧。




添加四个方向的按钮。
<button id="btn-left">left</button>
<button id="btn-right">right</button>
<button id="btn-top">top</button>
<button id="btn-down">down</button>

var btnLeft = document.getElementById('btn-left')
var btnRight = document.getElementById('btn-right')
var btnTop = document.getElementById('btn-top')
var btnDown = document.getElementById('btn-down')



在绘制图片前(new Image()前)。设置方向。相当于图片的第一行。代表向下走。
var dirIndex = 0;

然后将截取的y坐标改为dirIndex*92.75,绑定相关的按钮事件。
btnLeft.onclick = function(){
	dirIndex =1 ;  //第2行
}
btnRight.onclick = function(){
	dirIndex =2 ;  //第3行
}
btnTop.onclick = function(){
	dirIndex =3 ;  //第4行
}
btnDown.onclick = function(){
	dirIndex =0 ;  //第1行
}


点击效果:



阴影
// 设置阴影
ctx.fillStyle = 'red';
ctx.shadowColor = 'teal';  //颜色
ctx.shadowBlur = 10;  //模糊 ( 大于1 )
ctx.shadowOffsetX = 10;  //偏移
ctx.shadowOffsetY = 10;
ctx.fillRect(100,100,100,100);



渐变

// 线性渐变
var grd = ctx.createLinearGradient(0, 0, 170, 0);
grd.addColorStop(0,"black");
grd.addColorStop(0.5,"red");
grd.addColorStop(1,'white');
ctx.fillStyle = grd;
ctx.fillRect(0, 0, 300, 300);



// 圆形渐变
var rlg = ctx.createRadialGradient(300, 300, 10, 300, 300, 200);
rlg.addColorStop(0,"white");
rlg.addColorStop(0.5,"red");
rlg.addColorStop(1,'black');
ctx.fillStyle = rlg;
ctx.fillRect(100, 100, 400, 400);



绘制背景图

var pat = ctx.createPattern(img,repeat);  //img是DOM对象
ctx.rect(0, 0, 150, 100);
ctx.fillStyle = pat;
ctx.fill();


变换
ctx.scale(Scale Width, Scale Height);  //缩放当前绘图  1为100%
ctx.translate(X, Y);  //位移画布
ctx.rotate(Rotate Angle);  //旋转当前绘图
ctx.save();  //保存当前环境的状态
ctx.restore();  //返回之前保存过的路径状态和属性
ctx.globalAlpha = "Value between 0 & 1";  //绘制环境的透明度


例子:
// 状态1
ctx.fillStyle = "red";
ctx.fillRect(10, 10, 100, 100);

ctx.save();  //保存状态
ctx.translate(200, 200);  //把当前画布移动到200,200的位置
ctx.rotate(30* Math.PI / 180);  //旋转
ctx.scale(2, 2);  //缩放
ctx.globalAlpha = ".3";  //透明度

ctx.moveTo(0, 0);
ctx.lineTo(400, 0);
ctx.moveTo(0, 0);
ctx.lineTo(0, 400);
ctx.stroke();
ctx.fillRect(10, 10, 40, 40);
ctx.restore();  //返回之前保存过的路径状态和属性

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


  • 大小: 1.9 KB
  • 大小: 1.5 KB
  • 大小: 1.5 KB
  • 大小: 1.5 KB
  • 大小: 2.2 KB
  • 大小: 1.7 KB
  • 大小: 1.6 KB
  • 大小: 1.8 KB
  • 大小: 1.8 KB
  • 大小: 33.6 KB
  • 大小: 2.2 KB
  • 大小: 2.2 KB
  • 大小: 2.5 KB
  • 大小: 3.2 KB
  • 大小: 3 KB
  • 大小: 7.6 KB
  • 大小: 2.1 KB
  • 大小: 45 KB
  • 大小: 51.7 KB
  • 大小: 61 KB
  • 大小: 8.7 KB
  • 大小: 8.7 KB
  • 大小: 3.6 KB
  • 大小: 6.4 KB
  • 大小: 4.1 KB
  • 大小: 3.3 KB
  • 大小: 1.4 KB
  • 大小: 29.2 KB
  • 大小: 13.5 KB
分享到:
评论

相关推荐

    javaFX canvas用法交互的小例子程序 挤压后idea可以打开并运行

    在这个“javaFX canvas用法交互的小例子程序”中,主要涉及的是JavaFX的Canvas API,这是一个用于绘制2D图形的强大的低级接口。下面我们将深入探讨JavaFX Canvas的使用方法和交互设计。 Canvas是JavaFX中的一个图形...

    html2canvas属性和使用方法以及如何使用html2canvas将HTML内容写入Canvas生成图片

    在使用html2canvas之前,先了解一下其基本属性和使用方法是十分必要的。html2canvas接受一个HTML元素作为参数,这个元素可以是整个页面,也可以是页面的一部分。通过调用html2canvas()函数,并传入对应的HTML元素,...

    Canvas的使用方法

    本文将深入探讨Canvas的使用方法,尤其是如何利用Canvas和其Path API来创建自定义画板。 首先,Canvas是一个二维绘图上下文,可以通过`&lt;canvas&gt;`元素在HTML中声明。例如: ```html &lt;canvas id="myCanvas" width=...

    Android Canvas使用集合

    本篇文章将深入探讨Android Canvas的使用方法以及与之相关的集合操作。 Canvas是Android中的一个类,它提供了各种绘制方法,如drawRect(), drawCircle(), drawBitmap()等,用于在SurfaceView、ImageView等组件上...

    封装canvas各种方法的vue组件

    在本例中,“封装canvas各种方法的vue组件”意味着开发者已经将常见的Canvas操作(如绘图、文字处理等)封装在一个自定义的Vue组件里,方便在项目中多次使用,提高了代码的复用性和可维护性。 其次,`Canvas API`...

    HTML5 画布canvas使用方法

    1. canvas基本使用方法: - canvas元素的使用,首先需要在HTML中定义一个canvas标签。该标签必须包含一个id属性,以便后续用JavaScript进行操作。同时,可以设置width和height属性来定义canvas的大小。 - 示例代码...

    Canvas的经典用法

    这个“Canvas的经典用法”可能包含了多个实例,帮助我们深入理解并掌握Canvas的基本操作和高级特性。 1. **基本概念与设置** - `canvas`元素:在HTML中,我们通过`&lt;canvas&gt;`标签来创建一个画布,它是一个矩形区域...

    学生学习最新H5控件canvas简单易学.zip

    这个压缩包"学生学习最新H5控件canvas简单易学.zip"显然是为初学者设计的,旨在帮助他们快速掌握HTML5中的canvas用法,避免了传统Flash与JavaScript交互的复杂性。 `&lt;canvas&gt;`元素是一个二维绘图上下文,通过...

    html2canvas将HTML内容写入Canvas生成图片 uniapp

    - 最后,通过Canvas的toDataURL方法,可以将绘制好的Canvas内容转换为data URL,即可以直接使用的图片URL。 2. **uniAPP集成html2canvas**: - 在uniAPP项目中,可以通过npm或yarn安装html2canvas库,然后在...

    Android-实现在Kotlin中更方便使用canvas

    首先,我们需要了解Canvas的基本用法。在Android中,通常通过`onDraw()`方法在View的生命周期中调用Canvas,如在自定义View中: ```kotlin class CustomView(context: Context, attrs: AttributeSet?) : View...

    svg转img所需 html2canvas方法,svg转canvas所需canvg方法

    以上就是使用`html2canvas`和`canvg`库进行SVG到IMG以及SVG到CANVAS转换的方法。在实际应用中,根据项目需求,可能还需要处理SVG的样式、透明度、尺寸等细节问题,以及考虑兼容性和性能优化。在使用这两个库时,务必...

    canvas实现遮罩效果

    1. 将图片作为Canvas背景:使用`drawImage()`方法将图片加载到Canvas中,然后在上面绘制遮罩。 ```javascript var img = new Image(); img.src = 'your-image-url.jpg'; img.onload = function() { ctx.drawImage...

    ec-canvas动态加载

    这种情况下,使用EC-Canvas的动态加载功能可以避免一次性加载大量资源,降低页面初始化时间。 2. **按需加载**:EC-Canvas支持按需加载图表类型。例如,如果一个页面只使用柱状图和饼图,可以只加载这两种图表的...

    canvas简单实例详解

    这个“canvas简单实例详解”将带你深入了解Canvas的基本用法和常见操作,为你的网页开发添加丰富的视觉效果。 一、Canvas基本结构 Canvas元素在HTML中以`&lt;canvas&gt;`标签表示,可以通过ID来引用并进行JavaScript操作...

    Delphi Canvas方法在图片上写入文字.rar

    此外,使用DrawImage或StretchDraw方法可以在Canvas上绘制和拉伸图像。 在实际应用中,开发者可能会结合使用这些方法来创建自定义的图形用户界面元素,比如带有动态文本的按钮、带有水印的图片等。同时,考虑到性能...

    html2canvas(1.0.0)

    三、使用方法 使用html2canvas非常简单,只需要在HTML文档中引入库文件,然后调用其提供的API即可。基本使用步骤如下: 1. 引入库文件:在HTML头部添加html2canvas的CDN链接或者本地文件引用。 2. 创建实例:通过`...

    canvas使用外部字体

    请注意,由于跨域限制,直接在Canvas中使用`drawImage`方法加载ttf文件可能会遇到问题。此时,你可能需要在服务器端处理字体文件,或者使用数据URL方式加载。 总的来说,使用Canvas与外部字体结合,可以创建出更具...

    vnode2canvas基于Vue插件将虚拟DOM渲染到canvas中

    4. **绘制到canvas**:最后,插件会根据解析和转换的结果,使用canvas的API(如`fillRect`、`drawImage`、`strokeText`等)将元素逐一绘制到canvas上。 5. **事件绑定**:如果需要保持交互性,插件可能还需要模拟...

    Android canvas.save()和canvas.restore()的理解

    `save()`和`restore()`是`Canvas`中两个非常关键的方法,它们主要用于管理绘图状态,确保复杂绘图过程中的可逆性和精确性。在本文中,我们将深入理解这两个方法的作用以及如何在实际应用中使用它们。 首先,`canvas...

    使用Canvas类绘制android机器人

    在绘制过程中,我们可以使用save()和restore()方法来保存和恢复Canvas的状态。这对于进行多次绘制并且需要保持某些属性不变(如坐标变换或剪裁区域)的情况下非常有用。例如,在绘制机器人的不同部分时,可能会涉及...

Global site tag (gtag.js) - Google Analytics