1.1  六瓣花平移变换

平移变换是指图形从一个位置到另一个位置所作的直线移动。如果要把一个位于P(x,y)的点移到新位置P’(x’,y’),如图1,则只要在原坐标上加上平移距离Tx和Ty即可。

即  x’=x+Tx

y’=y+Ty

图1  点的平移

生成一个六瓣花型图案的基本数据,通过平移变换绘制8行8列共64个六瓣花型的图案。

编写如下的HTML代码。

<!DOCTYPE html>

<head>

<title>六瓣花平移变换</title>

<script type="text/javascript">

function draw(id)

{

var canvas=document.getElementById(id);

if (canvas==null)

return false;

var context=canvas.getContext('2d');

context.fillStyle="#EEEEFF";

context.fillRect(0,0,320,320);

context.strokeStyle="blue";

context.lineWidth=1;

var dig=Math.PI/64;

var x=new Array();

var y=new Array();

var r=40;

// 生成一个六瓣花型图案的基本数据

for (var i=0;i<=128;i++)

{

d=r/2*(0.8+Math.sin(18*i*dig)/5)*1.3;

t=d*(0.5+Math.sin(6*i*dig)/2);

x[i]=t*Math.cos(i*dig);

y[i]=t*Math.sin(i*dig);

}

// 通过平移变换绘制8行8列共64个六瓣花型的图案

for (var row=1;row<=8;row++)

for (var col=1;col<=8;col++)

{

// 计算平移量px和py

px=(2*col-1)/2*r;

py=(2*row-1)/2*r;

for (i=0;i<=128;i++)

{

x1=x[i]+px;

y1=y[i]+py;

if (i==0)

{

context.moveTo(x1,y1);

bx=x1;  by=y1;

}

else

context.lineTo(x1,y1);

}

}

context.lineTo(bx,by);

context.closePath();

context.stroke();

}

</script>

</head>

<body onload="draw('myCanvas');">

<canvas id="myCanvas" width="320" height="320">您的浏览器不支持canvas!

</canvas>

</body>

</html>

将上述HTML代码保存到一个html文本文件中,再在浏览器中打开包含这段HTML代码的html文件,可以看到在浏览器窗口中绘制出64个六瓣花型的图案,如图2所示。

图2  64个六瓣花型的图案

1.2  对称变换

对称变换的公式如下:

x’=ax+by

y’=cx+dy

当a,b,c,d 取不同值时,产生不同的对称变换。

(1)当b=c=0,a=-1,d=1 时,产生相对于y 轴对称的反射图形。

(2)当b=c=0,a=1,d=-1 时,产生相对于x 轴对称的反射图形。

(3)当b=c=0,a=d=-1 时,产生相对于原点对称的反射图形。

(4)当b=c=1,a=d=0 时,产生相对于直线y=x 对称的反射图形。

(5)当b=c=-1,a=d=0 时,产生相对于直线y=-x 对称的反射图形。

各对称变换如图3所示。

图3  对称变换

在半径为60的圆周上取5个等分点,用这5个点依次首尾连接画5条线,可以绘制出一个正多边形。用这个正多边形为原图,根据选择的方式,进行对称变换。

编写如下的HTML代码。

<!DOCTYPE html>

<head>

<title>对称变换</title>

<script type="text/javascript">

// 定义保存基本图案数据的数组

var x=new Array(10);

var y=new Array(10);

var dig=2*Math.PI/5;

for (var i=0;i<=5;i++)

{

x[i]=-75+60*Math.sin(i*dig);

y[i]=-75+60*Math.cos(i*dig);

}

function draw()

{

var sele=document.frm.shape.selectedIndex;

var canvas=document.getElementById("myCanvas");

if (canvas==null)

return false;

var context=canvas.getContext('2d');

context.fillStyle="#EEEEFF";

context.fillRect(0,0,300,300);

//绘制x轴、y轴(注意:我们不进行旋转,故y轴向下)

context.beginPath();

context.moveTo(0,150);

context.lineTo(285,150);

context.moveTo(150,0);

context.lineTo(150,285);

context.strokeStyle = "blue";

context.stroke();

context.fillStyle = "blue";

context.beginPath();

context.moveTo(285,145);

context.lineTo(295,150);

context.lineTo(285,155);

context.closePath();

context.fill();

context.beginPath();

context.moveTo(145,285);

context.lineTo(150,295);

context.lineTo(155,285);

context.closePath();

context.fill();

context.fillStyle="yellow";

context.strokeStyle="red";

context.lineWidth=1;

context.save();

context.translate(150,150);

context.beginPath();

context.moveTo(x[0],y[0]);

for (n=1;n<=5;n++)

{

context.lineTo(x[n],y[n]);

}

context.closePath();

context.stroke();

context.fill();

context.beginPath();

context.moveTo(x[0],y[0]);

context.lineTo(x[2],y[2]);

context.strokeStyle="black";

context.stroke();

context.fillStyle="red";

context.strokeStyle="yellow";

context.beginPath();

switch(sele)

{

case 1: b=c=0,a=1,d=-1; break;

case 2: b=c=0,a=-1,d=1; break;

case 3: b=c=0,a=d=-1; break;

case 4: b=c=1,a=d=0; break;

case 5: b=c=-1,a=d=0; break;

}

context.moveTo(a*x[0]+b*y[0],c*x[0]+d*y[0]);

for (n=1;n<=5;n++)

{

context.lineTo(a*x[n]+b*y[n],c*x[n]+d*y[n]);

}

context.closePath();

context.stroke();

context.fill();

context.beginPath();

context.moveTo(a*x[0]+b*y[0],c*x[0]+d*y[0]);

context.lineTo(a*x[2]+b*y[2],c*x[2]+d*y[2]);

context.strokeStyle="black";

context.stroke();

context.restore();

}

</script>

</head>

<body>

<form name="frm">对称方式选择:

<select name="shape" onchange="draw();">

<option>--请选择--</option>

<option>X轴对称</option>

<option>Y轴对称</option>

<option>原点对称</option>

<option>直线Y=X对称</option>

<option>直线Y=-X对称</option>

</select>

</form>

<br/>

<canvas id="myCanvas" width="300" height="300">您的浏览器不支持canvas!</canvas>

</body>

</html>

将上述HTML代码保存到一个html文本文件中,再在浏览器中打开包含这段HTML代码的html文件,可以看到在浏览器窗口中,出现“对称方式选择:”下拉列表框,提供5种对称方式的选择,改变选定的对称方式后,可以绘制出基本图案的相应对称变换图案。整个演示过程录屏后展示如图8所示。

图4  图形的对称变换 

JavaScript图形实例:图形的平移和对称变换的更多相关文章

  1. JavaScript图形实例:线段构图

    在“JavaScript图形实例:四瓣花型图案”和“JavaScript图形实例:蝴蝶结图案”中,我们绘制图形时,主要采用的方法是先根据给定的曲线参数方程计算出两点坐标,然后将两点用线段连接起来,线段 ...

  2. JavaScript图形实例:再谈IFS生成图形

    在“JavaScript图形实例:迭代函数系统生成图形”一文中,我们介绍了采用迭代函数系统(Iterated Function System,IFS)创建分形图案的一些实例.在该文中,仿射变换函数W的 ...

  3. JavaScript图形实例:随机SierPinski三角形

    在“JavaScript图形实例:SierPinski三角形”中,我们介绍了SierPinski三角形的基本绘制方法,在“JavaScript图形实例:迭代函数系统生成图形”一文中,介绍了采用IFS方 ...

  4. JavaScript动画实例:李萨如曲线

    在“JavaScript图形实例:阿基米德螺线”和“JavaScript图形实例:曲线方程”中,我们学习了利用曲线的方程绘制曲线的方法.如果想看看曲线是怎样绘制出来的,怎么办呢?编写简单的动画,就可以 ...

  5. JavaScript动画实例:递归分形图动态展示

    在“JavaScript图形实例:SierPinski三角形” 和“JavaScript图形实例:Levy曲线及其变形”等文章中我们介绍了通过递归生成分形图形的方法.我们可以将绘制的分形图形每隔一定的 ...

  6. JavaScript动画实例:曲线的绘制

    在“JavaScript图形实例:曲线方程”一文中,我们给出了15个曲线方程绘制图形的实例.这些曲线都是根据其曲线方程,在[0,2π]区间取一系列角度值,根据给定角度值计算对应的各点坐标,然后在计算出 ...

  7. JavaScript小实例:拖拽应用(二)

    经常在网站别人的网站的注册页中看到一个拖拽验证的效果,就是它的验证码刚开始不出来,而是有一个拖拽的条,你必须将这个拖拽条拖到底,验证码才出来,说了感觉跟没说一样,你还是不理解,好吧,我给个图你看看: ...

  8. javascript小实例,拖拽应用(一)

    前面我们将了一下拖拽的基本思想,理论是有了,那实践呢,可以运用到什么地方呢?下面就给大家带来一个用拖拽思想写的一个小实例,供大家参考,大致效果看下图: 就是这样一个简单的一个拖拽条,你可以把它理解为滚 ...

  9. JavaScript 小实例 - 表单输入内容检测,对页面的增删改

    JavaScript 小实例 - 表单输入内容检测,对页面的增删改 效果体验地址:https://xpwi.github.io/js/JavaScript01/jsForm.html 功能: 1.向页 ...

  10. 10种JavaScript特效实例让你的网站更吸引人

    我们有三种主要的方法(从难到易):自己动手写脚本;使用类似于jQuery和mooTools的JavaScript框架(可以让编写代码变得更容易些);使用能工作于现有的JavaScript框架下的提前预 ...

随机推荐

  1. Goland debug失败

    在使用goland使用debug调试代码出现 API server listening at: 127.0.0.1:56871could not launch process: debugserver ...

  2. 洛谷 P1076 寻宝(模拟 && 剪枝)

    嗯... 题目链接:https://www.luogu.org/problem/P1076 这道题的题意首先太难理解...并且细节太多... 可以用b[i][j]记录每个指示牌上的数字,a[i][j] ...

  3. eight(待考究)

    为什么明明结果都可以到达那种情况,步骤不一样就不给通过 QAQ 有哪位大佬提点一下,在下感激不尽~~~ 我的代码: #include <iostream>#include <queu ...

  4. 洛谷P1164小A点菜(01背包)

    题目背景 uim神犇拿到了uoi的ra(镭牌)后,立刻拉着基友小A到了一家……餐馆,很低端的那种. uim指着墙上的价目表(太低级了没有菜单),说:“随便点”. 题目描述 不过uim由于买了一些辅(e ...

  5. Update(Stage5):Kudu_javaApi使用_Spark整合

    Table of Contents: 2.3. 安装 Zookeeper 2.4. 安装 Hadoop 2.4. 安装 MySQL 2.5. 安装 Hive 2.6. 安装 Kudu 2.7. 安装 ...

  6. 根据class 属性判断所有的文本框必填

    <body> <!-- 遮罩层 --> <div id="hidediv" style="width: 100%;height: 100%; ...

  7. Nginx 七层反向代理

    目录 1.代理 2.正向代理 3.反向代理 4.Nginx 反向代理 5.Nginx 反向代理相关指令介绍 ①.listen ②.server_name ③.location ④.proxy_pass ...

  8. php 高级 PHP的垃圾回收机制

    PHP可以自动进行内存管理,清楚不再需要的对象.PHP使用了引用计数这种单纯的垃圾回收机制.每个对象都内含一个引用计数器,每个reference链接到对象,计数器加1,当reference离开生存空间 ...

  9. Go语言学习笔记(三)

    一.浮点数 1.概述 浮点类型用于存储带有小数点的数字 一个整数数值可以赋值给浮点类型但是一个整型变量不可以赋值给浮点类型 浮点数进行运算的结果是浮点数 Go语言中浮点类型有两个 float32 fl ...

  10. JavaScript - String对象,字符串,String包装类型

    1. 字符串 1.1 字符串的不可变性 var str = 'abc'; str = 'hello'; // 当重新给str赋值的时候,常量'abc'不会被修改,依然在内存中 // 重新给字符串赋值, ...