《canvas》之第7章 变形操作
第7章 变形操作
7.1 变形操作简介
文字或图片的位移、缩放、旋转、倾斜、选择、倾斜等变形效果。
变形操作方法
方法 | 说明 |
---|---|
translate() | 平移 |
scale() | 缩放 |
rotate() | 旋转 |
transform()、setTransform() | 变换矩阵 |
7.2 图形平移
7.2.1 translate()方法
不会改变图形型状和大小。
cxt.translate(x, y);
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<meta charset="utf-8" />
<script type="text/javascript">
function $$(id) {
return document.getElementById(id);
}
window.onload = function () {
var cnv = $$("canvas");
var cxt = cnv.getContext("2d");
//绘制矩形
cxt.fillStyle = "HotPink";
cxt.fillRect(30, 30, 50, 50);
//移动矩形
cxt.translate(50, 50);
cxt.fillRect(30, 30, 50, 50); //重绘,这里仍然是fillRect(30, 30, 50, 50)
}
</script>
</head>
<body>
<canvas id="canvas" width="200" height="150" style="border:1px dashed gray"></canvas>
</body>
</html>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<meta charset="utf-8" />
<script type="text/javascript">
function $$(id) {
return document.getElementById(id);
}
window.onload = function () {
var cnv = $$("canvas");
var cxt = cnv.getContext("2d");
//绘制初始图形
cxt.fillStyle = "HotPink";
cxt.fillRect(30, 30, 50, 50);
//添加按钮点击事件
$$("btn").onclick = function () {
cxt.translate(10, 10);
//cxt.fillStyle = "HotPink";
cxt.fillRect(30, 30, 50, 50);
}
}
</script>
</head>
<body>
<canvas id="canvas" width="200" height="150" style="border:1px dashed gray;"></canvas><br />
<input id="btn" type="button" value="移动" />
</body>
</html>
7.2.2 clearRect()方法清空canvas
cxt.clearRect(0, 0, cnv.width, cnv.height);
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<meta charset="utf-8" />
<script type="text/javascript">
function $$(id) {
return document.getElementById(id);
}
window.onload = function () {
var cnv = $$("canvas");
var cxt = cnv.getContext("2d");
//绘制初始图形
cxt.fillStyle = "HotPink";
cxt.fillRect(30, 30, 50, 50);
$$("btn").onclick = function () {
cxt.clearRect(0, 0, cnv.width, cnv.height);
cxt.translate(10, 10);
//cxt.fillStyle = "HotPink";
cxt.fillRect(30, 30, 50, 50);
}
}
</script>
</head>
<body>
<canvas id="canvas" width="200" height="150" style="border:1px dashed gray;"></canvas><br />
<input id="btn" type="button" value="移动" />
</body>
</html>
7.3 图形缩放
7.3.1 scale()方法
cxt.scale(x, y);
-
x,y可取负值。
-
基于坐标原点缩放。
-
在上一次状态基础上缩放。
-
图形缩放
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<meta charset="utf-8" />
<script type="text/javascript">
function $$(id) {
return document.getElementById(id);
}
window.onload = function () {
var cnv = $$("canvas");
var cxt = cnv.getContext("2d");
//绘制初始图形
cxt.fillStyle = "HotPink";
cxt.fillRect(30, 30, 50, 50);
//缩放操作
cxt.scale(1.5, 1.5);
cxt.fillStyle = "LightSkyBlue";
cxt.fillRect(30, 30, 50, 50);
}
</script>
</head>
<body>
<canvas id="canvas" width="200" height="150" style="border:1px dashed gray"></canvas>
</body>
</html>
- 放大缩小
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<meta charset="utf-8" />
<script type="text/javascript">
function $$(id) {
return document.getElementById(id);
}
window.onload = function () {
var cnv = $$("canvas");
var cxt = cnv.getContext("2d");
//绘制初始图形
cxt.fillStyle = "HotPink";
cxt.fillRect(30, 30, 50, 50);
//图形放大
$$("btn-big").onclick = function () {
cxt.scale(1.5, 1.5);
cxt.fillStyle = "#9966FF";
cxt.fillRect(30, 30, 50, 50);
}
//图形缩小
$$("btn-small").onclick = function () {
cxt.scale(0.5, 0.5);
cxt.fillStyle = "LightSkyBlue";
cxt.fillRect(30, 30, 50, 50);
}
}
</script>
</head>
<body>
<canvas id="canvas" width="200" height="150" style="border:1px dashed gray"></canvas><br />
<input id="btn-big" type="button" value="放大" />
<input id="btn-small" type="button" value="缩小" />
</body>
</html>
7.3.2 scale()方法的负作用
- 左上角坐标会缩放。
- 线条宽度也会缩放。
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<meta charset="utf-8" />
<script type="text/javascript">
function $$(id) {
return document.getElementById(id);
}
window.onload = function () {
var cnv = $$("canvas");
var cxt = cnv.getContext("2d");
cxt.lineWidth = 4;
cxt.strokeStyle = "HotPink";
cxt.strokeRect(30, 30, 50, 50);
//图形放大
$$("btn-big").onclick = function () {
cxt.scale(1.5, 1.5);
cxt.strokeRect(30, 30, 50, 50);
}
}
</script>
</head>
<body>
<canvas id="canvas" width="200" height="150" style="border:1px dashed gray"></canvas><br />
<input id="btn-big" type="button" value="放大" />
</body>
</html>
7.4 图形旋转
7.4.1 rotate()方法
cxt.rotate(angle);
angle>0,顺时针,基于原点旋转,基于上一次状态旋转。
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<meta charset="utf-8" />
<script type="text/javascript">
function $$(id) {
return document.getElementById(id);
}
window.onload = function () {
var cnv = $$("canvas");
var cxt = cnv.getContext("2d");
cxt.fillStyle = "HotPink";
cxt.fillRect(30, 30, 50, 50);
$$("btn").onclick = function () {
cxt.rotate(-3 * Math.PI / 180); //逆时针旋转30°
cxt.fillStyle = "LightSkyBlue ";
cxt.fillRect(30, 30, 50, 50); //注意,这里仍然是fillRect(30, 30, 50, 50)
}
}
</script>
</head>
<body>
<canvas id="canvas" width="200" height="150" style="border:1px dashed gray;"></canvas><br />
<input id="btn" type="button" value="旋转" />
</body>
</html>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<meta charset="utf-8" />
<script type="text/javascript">
function $$(id) {
return document.getElementById(id);
}
window.onload = function () {
var cnv = $$("canvas");
var cxt = cnv.getContext("2d");
cxt.fillStyle = "HotPink";
cxt.fillRect(30, 30, 50, 50);
var degree = 0;
setInterval(function () {
cxt.rotate(degree * Math.PI / 180);
cxt.fillRect(30, 30, 50, 50);
degree++;
}, 1000); //每隔1000ms调用一次函数
}
</script>
</head>
<body>
<canvas id="canvas" width="200" height="150" style="border:1px dashed gray;"></canvas>
</body>
</html>
7.4.2 改变旋转中心
translate()+rotate()。
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<meta charset="utf-8" />
<script type="text/javascript">
function $$(id) {
return document.getElementById(id);
}
window.onload = function () {
var cnv = $$("canvas");
var cxt = cnv.getContext("2d");
var i = 0;
var rectWidth = 100;
var rectHeight = 50;
setInterval(function () {
i++;
cxt.clearRect(0, 0, cnv.width, cnv.height);
cxt.save();
cxt.translate(cnv.width/2, cnv.height/2); //将坐标移动到中心
cxt.rotate(Math.PI*(i/100)); //累进旋转
cxt.fillStyle = "HotPink";
cxt.fillRect(-rectWidth/2, -rectHeight/2, rectWidth, rectHeight); //填充矩形
cxt.restore();
}, 10);
}
</script>
</head>
<body>
<canvas id="canvas" width="200" height="150" style="border:1px dashed gray;"></canvas>
</body>
</html>
7.5 变换矩阵
transform()方法
transform()方法实现平移、缩放和旋转。
cxt.transform(a, b, c, d, e,f);
a,水平缩放。
b,水平倾斜。
c,垂直倾斜。
d,垂直缩放。
e,水平移动。
f,垂直移动。
- 变换矩阵
( a c e b d f 0 0 1 ) \begin{pmatrix} a & c & e \\ b & d & f \\ 0 & 0 & 1 \end{pmatrix} ab0cd0ef1
- 平移
cxt.transform(1, 0, 0, 1, e,f);
cxt.translate(e, f);
( x 1 y 1 1 ) = ( 1 0 e 0 1 f 0 0 1 ) ( x y 1 ) \begin{matrix} \left(\begin{array}{rr} x1 \\ y1 \\ 1 \\ \end{array}\right) & = & \left(\begin{array}{rr} 1 & 0 & e \\ 0 & 1 & f \\ 0 & 0 & 1 \end{array}\right) & \left(\begin{array}{rr} x \\ y \\ 1 \\ \end{array}\right) \end{matrix} x1y11 = 100010ef1 xy1
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<meta charset="utf-8" />
<script type="text/javascript">
function $$(id) {
return document.getElementById(id);
}
window.onload = function () {
var cnv = $$("canvas");
var cxt = cnv.getContext("2d");
//绘制初始图形
cxt.fillStyle = "HotPink";
cxt.fillRect(30, 30, 50, 50);
$$("btn").onclick = function () {
cxt.clearRect(0, 0, cnv.width, cnv.height);
cxt.transform(1, 0, 0, 1, 10, 10);
//cxt.fillStyle = "HotPink";
cxt.fillRect(30, 30, 50, 50);
}
}
</script>
</head>
<body>
<canvas id="canvas" width="200" height="150" style="border:1px dashed gray;"></canvas><br />
<input id="btn" type="button" value="移动" />
</body>
</html>
- 缩放
cxt.transform(a, 0, 0, d, 0, 0);
cxt.scale(a, d);
( x 1 y 1 1 ) = ( a 0 0 0 d 0 0 0 1 ) ( x y 1 ) \begin{matrix} \left(\begin{array}{rr} x1 \\ y1 \\ 1 \\ \end{array}\right) & = & \left(\begin{array}{rr} a & 0 & 0 \\ 0 & d & 0 \\ 0 & 0 & 1 \end{array}\right) & \left(\begin{array}{rr} x \\ y \\ 1 \\ \end{array}\right) \end{matrix} x1y11 = a000d0001 xy1
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<meta charset="utf-8" />
<script type="text/javascript">
function $$(id) {
return document.getElementById(id);
}
//定义绘制图形的函数
window.onload = function () {
var cnv = $$("canvas");
var cxt = cnv.getContext("2d");
cxt.fillStyle = "HotPink";
cxt.fillRect(30, 30, 50, 50);
//图形放大
$$("btn-big").onclick = function () {
cxt.transform(1.5, 0, 0, 1.5, 0, 0);
cxt.fillStyle = "#9966FF";
cxt.fillRect(30, 30, 50, 50);
}
//图形缩小
$$("btn-small").onclick = function () {
cxt.transform(0.5, 0, 0, 0.5, 0, 0);
cxt.fillStyle = "LightSkyBlue";
cxt.fillRect(30, 30, 50, 50);
}
}
</script>
</head>
<body>
<canvas id="canvas" width="200" height="150" style="border:1px dashed gray"></canvas><br />
<input id="btn-big" type="button" value="放大" />
<input id="btn-small" type="button" value="缩小" />
</body>
</html>
- 旋转
cxt.transform(cos(angle), sin(angle), -sin(angle), cos(angle), 0, 0);
cxt.rotate(angle);
( x 1 y 1 1 ) = ( c o s ( a n g l e ) − s i n ( a n g l e ) 0 s i n ( a n g l e ) c o s ( a n g l e ) 0 0 0 1 ) ( x y 1 ) \begin{matrix} \left(\begin{array}{rr} x1 \\ y1 \\ 1 \\ \end{array}\right) & = & \left(\begin{array}{rr} cos(angle) & -sin(angle) & 0 \\ sin(angle) & cos(angle) & 0 \\ 0 & 0 & 1 \end{array}\right) & \left(\begin{array}{rr} x \\ y \\ 1 \\ \end{array}\right) \end{matrix} x1y11 = cos(angle)sin(angle)0−sin(angle)cos(angle)0001 xy1
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<meta charset="utf-8" />
<style type="text/css">
body {
text-align: center;
}
</style>
<script type="text/javascript">
function $$(id) {
return document.getElementById(id);
}
//定义绘制图形的函数
window.onload = function () {
var cnv = $$("canvas");
var cxt = cnv.getContext("2d");
cxt.fillStyle = "HotPink";
cxt.fillRect(30, 30, 50, 50);
$$("btn").onclick = function () {
var angle = -30 * Math.PI / 180 //逆时针旋转30°
//cxt.rotate(angle);
cxt.transform(Math.cos(angle), Math.sin(angle), -Math.sin(angle), Math.cos(angle), 0, 0);
cxt.fillStyle = "LightSkyBlue ";
cxt.fillRect(30, 30, 50, 50);
}
}
</script>
</head>
<body>
<canvas id="canvas" width="200" height="150" style="border:1px dashed gray;"></canvas><br />
<input id="btn" type="button" value="旋转" />
</body>
</html>
- 居中旋转
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<meta charset="utf-8" />
<script type="text/javascript">
function $$(id) {
return document.getElementById(id);
}
window.onload = function () {
var cnv = $$("canvas");
var cxt = cnv.getContext("2d");
var i = 0;
var angle = 0;
var rectWidth = 100;
var rectHeight = 50;
setInterval(function () {
i++;
cxt.clearRect(0, 0, cnv.width, cnv.height);
cxt.save();
angle = Math.PI * (i / 100);
cxt.transform(Math.cos(angle), Math.sin(angle), -Math.sin(angle), Math.cos(angle), cnv.width / 2, cnv.height / 2);
cxt.fillStyle = "HotPink";
cxt.fillRect(-rectWidth / 2, -rectHeight / 2, rectWidth, rectHeight); //填充矩形
cxt.restore();
}, 10);
}
</script>
</head>
<body>
<canvas id="canvas" width="200" height="150" style="border:1px dashed gray;"></canvas>
</body>
</html>
7.5.2 setTransform()方法
transfomr()方法基于上一次状态变换,setTransform()方法直接设置图形状态,然后变换。
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<meta charset="utf-8" />
<script type="text/javascript">
function $$(id) {
return document.getElementById(id);
}
window.onload = function () {
var cnv = $$("canvas");
var cxt = cnv.getContext("2d");
cxt.fillStyle = "yellow";
cxt.fillRect(0, 0, 100, 50)
cxt.setTransform(1, 0.5, -0.5, 1, 30, 10);
cxt.fillStyle = "red";
cxt.fillRect(0, 0, 100, 50);
cxt.setTransform(1, 0.5, -0.5, 1, 30, 10);
cxt.fillStyle = "blue";
cxt.fillRect(0, 0, 100, 50);
cxt.transform(1, 0.5, -0.5, 1, 30, 10);
cxt.fillStyle = "red";
cxt.fillRect(0, 0, 100, 50);
cxt.transform(1, 0.5, -0.5, 1, 30, 10);
cxt.fillStyle = "blue";
cxt.fillRect(0, 0, 100, 50);
}
</script>
</head>
<body>
<canvas id="canvas" width="200" height="150" style="border:1px dashed gray"></canvas>
</body>
</html>
7.6 深入变形操作
- 变形操作用于图片
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<meta charset="utf-8" />
<script type="text/javascript">
function $$(id) {
return document.getElementById(id);
}
window.onload = function () {
var cnv = $$("canvas");
var cxt = cnv.getContext("2d");
//创建image对象
var image = new Image();
image.src = "images/princess.png";
image.onload = function () {
cxt.drawImage(image, 10, 10);
cxt.translate(50, 50);
cxt.drawImage(image, 10, 10);
}
}
</script>
</head>
<body>
<canvas id="canvas" width="200" height="150" style="border:1px dashed gray;"></canvas>
</body>
</html>
- 变形操作用于文字
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<meta charset="utf-8" />
<script type="text/javascript">
function $$(id) {
return document.getElementById(id);
}
window.onload = function () {
var cnv = $$("canvas");
var cxt = cnv.getContext("2d");
var text = "绿叶学习网";
cxt.font = "bold 20px 微软雅黑";
cxt.strokeStyle = "HotPink";
cxt.strokeText(text, 10, 30);
cxt.translate(50, 50);
cxt.scale(1.5, 1.5);
cxt.rotate(30 * Math.PI / 180);
cxt.strokeText(text, 10, 30);
}
</script>
</head>
<body>
<canvas id="canvas" width="200" height="150" style="border:1px dashed gray;"></canvas>
</body>
</html>
7.7 绘制绚丽图形
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<meta charset="utf-8" />
<script type="text/javascript">
function $$(id) {
return document.getElementById(id);
}
window.onload = function () {
var cnv = $$("canvas");
var cxt = cnv.getContext("2d");
cxt.translate(150, 0);
cxt.fillStyle = "rgba(255, 0, 0, 0.25)";
for (var i = 0; i < 50; i++) {
cxt.translate(25, 25); //图形平移
cxt.scale(0.95, 0.95); //图形缩放
cxt.rotate(Math.PI / 10); //图形旋转
cxt.fillRect(0, 0, 100, 50);
}
}
</script>
</head>
<body>
<canvas id="canvas" width="200" height="180" style="border:1px dashed gray;"></canvas>
</body>
</html>
7.8 绘制彩虹
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<meta charset="utf-8" />
<script type="text/javascript">
function $$(id) {
return document.getElementById(id);
}
window.onload = function () {
var cnv = $$("canvas");
var cxt = cnv.getContext("2d");
//定义数组,存储7种颜色
var colors = ["red", "orange", "yellow", "green", "blue", "navy", "purple"];
var rStep = 12;
cxt.lineWidth = rStep;
//cxt.translate(50, 0);
//循环绘制圆弧
for (var i = 0; i < colors.length; i++) {
//定义每次向下移动rStep的变换矩阵
cxt.translate(0, rStep);
//定义颜色
cxt.strokeStyle = colors[i];
//绘制圆弧
cxt.beginPath();
cxt.arc(cnv.width/2, 100, cnv.width/2, 0, 180 * Math.PI / 180, true);
cxt.stroke();
}
}
</script>
</head>
<body>
<canvas id="canvas" width="200" height="150" style="border:1px dashed gray;"></canvas>
</body>
</html>