《canvas》之第7章 变形操作

130 篇文章 4 订阅
20 篇文章 4 订阅

第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
  1. 平移
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>
  1. 缩放
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>
  1. 旋转
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)0sin(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>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值