1、保存与恢复canvas状态

ctx.save();暂时将当前的状态保存到堆中

ctx.restore();该方法用于将上一个保存的状态从堆中再次取出,恢复该状态的所有设置。

 <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
*{padding: 0;margin:0;}
body{background: #1b1b1b;}
#div1{margin:50px auto; width:300px; height: 300px;}
canvas{background: #fff;}
</style>
<script type="text/javascript">
window.onload = function(){
var c = document.getElementById('myCanvas');
var context = c.getContext('2d'); //开始绘制矩形
context.fillStyle = '#f0f';
context.strokeStyle = 'blue';
context.fillRect(20,20,100,100);
context.strokeRect(20,20,100,100);
context.fill();
context.stroke(); //保存当前canvas状态
context.save(); //绘制另外一个矩形
context.fillStyle = '#f00';
context.strokeStyle = 'green';
context.fillRect(140,20,100,100);
context.strokeRect(140,20,100,100);
context.fill();
context.stroke(); //恢复第一个矩形的状态
context.restore(); //绘制两个矩形
context.fillRect(20,140,50,50);
context.strokeRect(80,140,50,50); };
</script>
</head>
<body>
<div id="div1">
<canvas id="myCanvas" width="300" height="200"></canvas>
</div>
</body>
</html>

效果展示:

2、移动坐标空间

context.translate(dx,dy); dx,dy分别表示坐标原点沿水平和垂直两个方向的偏移量。(在图形变换之前,最好使用save()方法保存当前状态的好习惯。使用restore()方法恢复原来的状态)。

 <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
*{padding: 0;margin:0;}
body{background: #1b1b1b;}
#div1{margin:50px auto; width:300px; height: 300px;}
canvas{background: #fff;}
</style>
<script type="text/javascript">
window.onload = function(){
draw();
};
function drawTop(ctx,fillStyle){
ctx.fillStyle = fillStyle;
ctx.beginPath();
ctx.arc(0,0,30,0,Math.PI,true);
ctx.closePath();
ctx.fill();
} function drawGrip(ctx){
ctx.save();
ctx.fillStyle = 'blue';
ctx.fillRect(-1.5,0,1.5,40);
ctx.beginPath();
ctx.arc(-5,40,4,Math.PI,Math.PI*2,true);
ctx.stroke();
ctx.closePath();
ctx.restore();
} function draw(){ var ctx = document.getElementById('myCanvas').getContext('2d');
ctx.translate(80,80); for(var i=0; i<10; i++){
ctx.save();
ctx.translate(60*i,0);
drawTop(ctx,'rgb('+(30*i)+','+(255-30*i)+',255)');
drawGrip(ctx);
ctx.restore();
} }
</script>
</head>
<body>
<div id="div1">
<canvas id="myCanvas" width="700" height="300"></canvas>
</div>
</body>
</html>

效果展示:

3、旋转坐标空间

context.rotate(angle);  该方法只有一个参数 旋转角度angle,旋转角度以顺时针方向为正方向,以弧度为单位,旋转中心为canvas的原点

 <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
*{padding: 0;margin:0;}
body{background: #1b1b1b;}
#div1{margin:50px auto; width:300px; height: 300px;}
canvas{background: #fff;}
</style>
<script type="text/javascript">
window.onload = function(){
draw();
};
function drawTop(ctx,fillStyle){
ctx.fillStyle = fillStyle;
ctx.beginPath();
ctx.arc(0,0,30,0,Math.PI,true);
ctx.closePath();
ctx.fill();
}
function drawGrip(ctx){
ctx.save();
ctx.fillStyle = 'blue';
ctx.fillRect(-1.5,0,1.5,40);
ctx.beginPath();
ctx.strokeStyle = 'blue';
ctx.arc(-5,40,4,Math.PI,Math.PI*2,true);
ctx.stroke();
ctx.closePath();
ctx.restore();
}
function draw(){
var c = document.getElementById('myCanvas');
var ctx = c.getContext('2d');
ctx.translate(150,150); for(var i=0; i<8; i++){
ctx.save();
ctx.rotate(Math.PI*(2/4+i/4));
ctx.translate(0,-100);
drawTop(ctx,'rgb('+(30*i)+','+(255-30*i)+',255)');
drawGrip(ctx);
ctx.restore();
}
}
</script>
</head>
<body>
<div id="div1">
<canvas id="myCanvas" width="300" height="300"></canvas>
</div>
</body>
</html>

效果展示:

4、缩放图形

ctx.scale(x,y); 其中x为x轴的缩放,y为y轴的缩放,如果要缩小,值为小于1的数值,如果要放大,值为大于1的数值。

 <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
*{padding: 0;margin:0;}
body{background: #1b1b1b;}
#div1{margin:50px auto; width:300px; height: 300px;}
canvas{background: #fff;}
</style>
<script type="text/javascript">
window.onload = function(){
draw();
}; function draw(){
var c = document.getElementById('myCanvas');
var ctx = c.getContext('2d');
ctx.translate(180,20); for(var i=0; i<80; i++){
ctx.save();
ctx.translate(30,30);
ctx.scale(0.95,0.95);
ctx.rotate(Math.PI/12);
ctx.beginPath();
ctx.fillStyle = 'red';
ctx.globalAlpha = '0.4';
ctx.arc(0,0,50,0,Math.PI*2,true);
ctx.closePath();
ctx.fill();
}
}
</script>
</head>
<body>
<div id="div1">
<canvas id="myCanvas" width="300" height="300"></canvas>
</div>
</body>
</html>

效果展示:

5、矩阵变换

transform方法用于直接对变形矩阵作修改,即进行矩阵变形。

context.transform(m11,m12,m21,m22,dx,dy);   该方法必须将当前的变换矩阵与下面的矩阵进行乘法运算。

即:

m11(默认为1) m21(默认为0) dx
m12(默认为0) m22(默认为1) dy
0 0 1

也就是说假设A(x,y)要变换成B(x’,y’)可以通过乘以上述矩阵即可得到。

一:平移(translate), translate可以用下面的方法替代

如上图所示:

x’=x+dx

y’=y+dy

即:

其中dx为原点沿着x轴移动的数值,y为原点沿着y轴移动的数值。

context.translate(x,y)可以用下面的transform方法来替代:

context.transform(0,1,1,0,dx,dy); 或 context.transform(1,0,0,1,dx,dy);

二、缩放:  scale(x,y) 

x’=m11*x

y’=m22*y

x'=m12*x

y'=m21*y

(其中,m11、m22 和m12、m21分别表示在x轴和y轴上的缩放倍数)

则:scale(x,y); 可以通过下面的transform发放来替代:

context.transform(m11,0,0,m22,0,0);  或 context.transform(0,m12,m21,0,0,0);


三、旋转: rotate(angle);

可以用下面的transform方法来替代:

context.transform(cosΘ,sinΘ,-sinΘ,cosΘ,0,0);

其中Θ为旋转的角度,dx,dy都为0表示坐标原点不变。

如图:x' = x*cosΘ - y*sinΘ

y' = x*sinΘ + y*cosΘ

也即是

则:

context.transform(Math.cos(θ*Math.PI/180),Math.sin(θ*Math.PI/180),

-Math.sin(θ*Math.PI/180),Math.cos(θ*Math.PI/180),0,0)可以替代context.rotate(θ)。

也可以使用

context.transform(-Math.sin(θ*Math.PI/180),Math.cos(θ*Math.PI/180),

Math.cos(θ*Math.PI/180),Math.sin(θ*Math.PI/180), 0,0)替代。

eg: context.transform(0.95,0,0,0.95,30,30); 可以替代 context.translate(30,30); context.scale(0.95.0.95);

setTransform方法用于将当前的变化矩阵 重置 为最初的矩阵,然后以相同的参数调用transform方法,即先set(重置),再transform(变换)

用法: context.setTransform(m11,m12,m21,m22,dx,dy);

 <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
*{padding: 0;margin:0;}
body{background: #1b1b1b;}
#div1{margin:50px auto; width:300px; height: 300px;}
canvas{background: #fff;}
</style>
<script type="text/javascript">
window.onload = function(){
draw();
}; function draw(){
var c = document.getElementById('myCanvas');
var ctx = c.getContext('2d');
ctx.translate(200,20); for(var i=0; i<80; i++){
ctx.save();
ctx.transform(0.95,0,0,0.95,30,30);
ctx.rotate(Math.PI/12);
ctx.beginPath();
ctx.fillStyle = 'red';
ctx.globalAlpha = '0.4';
ctx.arc(0,0,50,0,Math.PI*2,true);
ctx.closePath();
ctx.fill();
} ctx.setTransform(1,0,0,1,10,10); //将前面的矩阵恢复为最初的矩阵,即恢复最初的原点,然后将坐标原点改为(10,10),并以新的坐标绘制一个蓝色的矩形
ctx.fillStyle = 'blue';
ctx.fillRect(0,0,50,50);
ctx.fill(); }
</script>
</head>
<body>
<div id="div1">
<canvas id="myCanvas" width="700" height="300"></canvas>
</div>
</body>
</html>

 效果显示:

canvas之图形的变化(平移,缩放,旋转)的更多相关文章

  1. WPF/Silverlight中图形的平移,缩放,旋转,倾斜变换演示

    原文:WPF/Silverlight中图形的平移,缩放,旋转,倾斜变换演示 为方便描述, 这里仅以正方形来做演示, 其他图形从略. 运行时效果图:XAML代码:// Transform.XAML< ...

  2. 图片在 canvas 中的 选中/平移/缩放/旋转,包含了所有canvas的2D变化,让你认识到数学的重要性

    1.介绍 canvas 已经出来好久了,相信大家多少都有接触. 如果你是前端页面开发/移动开发,那么你肯定会有做过图片上传处理,图片优化,以及图片合成,这些都是可以用 canvas 实现的. 如果你是 ...

  3. Graphics平移缩放旋转(转载)+点睛

    点睛:可以进行多次旋转和平移,也就是平移以后再平移,旋转以后再旋转,有时候一次达不到要求,如果你想一次调整完美的话很麻烦,所以最好多次,上代码 private void btnTranslate_Cl ...

  4. 二维坐标的平移,旋转,缩放及matlab实现

    本文结合matlab 软件解释二维坐标系下的平移,旋转,缩放 首先确定点在二维坐标系下的表达方法,使用一个1*3矩阵: Pt = [x,y,1] 其中x,y 分别为点的X,Y坐标,1为对二维坐标的三维 ...

  5. threeJS创建mesh,创建平面,设置mesh的平移,旋转、缩放、自传、透明度、拉伸

    这个小案例是当初我在学习的时候,小的一个小案例,代码还需要进一步优化:还请谅解~~:主要用到了threeJS创建mesh,创建平面,设置mesh的平移,旋转.缩放.自传.透明度.拉伸等这些小功能: 采 ...

  6. 【转载】Unity中矩阵的平移、旋转、缩放

    By:克森 简介 在这篇文章中,我们将会学到几个概念:平移矩阵.旋转矩阵.缩放矩阵.在学这几个基本概念的同时,我们会用到 Mesh(网格).数学运算.4x4矩阵的一些简单的操作.但由于克森也是新手,文 ...

  7. Matlab 图像平移、旋转、缩放、镜像

    今天学习了用Matlab实现对图像的基本操作.在Matlab中,图像是按照二维矩阵的形式表示的.所以对图像的操作就是对矩阵的操作. 对图像进行缩放.平移.旋转,都可以转化为矩阵的运算. 关于变换矩阵的 ...

  8. Android(java)学习笔记237:多媒体之图形的变化处理

    1.图形的缩放 (1)布局文件activity_main.xml如下: <LinearLayout xmlns:android="http://schemas.android.com/ ...

  9. Android(java)学习笔记180:多媒体之图形的变化处理

    1. 图形的缩放 (1)布局文件activity_main.xml如下: <LinearLayout xmlns:android="http://schemas.android.com ...

随机推荐

  1. __all__方法的作用

    在__all__里面写了谁,到时候就只能用谁,其他的用不了,from 模块 import *时就只能用__all__里的 __all__=['test1','Test'] def test1(): p ...

  2. Linux系统——引导过程与服务控制

    一.Linux开机启动原理(十步) (1)开机自检BIOS 开机检测,主板检测 (2)MBR引导 硬盘512字节 (3)GRUB菜单 操作系统菜单 (4)加载内核(kernel) 启动操作系统核心,根 ...

  3. HDU 1532 Drainage Ditches(网络流模板题)

    题目大意:就是由于下大雨的时候约翰的农场就会被雨水给淹没,无奈下约翰不得不修建水沟,而且是网络水沟,并且聪明的约翰还控制了水的流速, 本题就是让你求出最大流速,无疑要运用到求最大流了.题中m为水沟数, ...

  4. Gym - 100548H The Problem to Make You Happy 2014-2015 ACM-ICPC, Asia Xian Regional Contest (BFS+博弈)

    题意:Bob和Alice在一张有向无环图上移动,给定二者的起点,Bob先手.Bob的失败条件是不能移动或者与Alice相遇.两个人都采取最优策略,求Bob是否会赢 分析:银牌题.先确定所有的失败状态, ...

  5. [转]Ubuntu使用Wireshark找不到interface的解决方法

    Wireshark是一款强大的有图形界面的网络封包分析工具. dumpcap需要root权限才能使用的,以普通用户打开Wireshark,Wireshark当然没有权限使用dumpcap进行截取封包. ...

  6. 使用Xib创建自定义视图(不是cell)时需要注意的问题

    开发项目过程中,有些地方不免会用到Xib来提高开发效率,如果你的手速够快,写代码建视图,我并不反对这样做.因为我以前也是纯手写代码开发. 进入正题,Xib好用,但是这些下面这些问题需要注意一下. 问题 ...

  7. WEB项目异常处理

    package cn.rest.advice; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger;impor ...

  8. 获取Json字符串中某个key对应的value

    JSONObject jsonObj= JSONObject.fromObject(jsonStr); String value= jsonObj.getString(key);

  9. Nginx访问控制_IP访问控制(http_access_module)原理、局限性、解决方法讲解

    基于IP的访问控制,基于Nginx的http_access_module模块,是Nginx本身内置的模块,不需要安装的时候配置.也就是允许哪些IP访问,不允许哪些IP访问 server { liste ...

  10. 如何用纯 CSS 创作一个单元素抛盒子的 loader

    效果预览 在线演示 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/qKwXbx 可交互视频 ...