• 【Canvas】JavaScript用Canvas制作美丽的对称图案


    生活中有看到一个对称图案,看着很美,于是想到,试试用Canvas试着画对称图形来,想到就做,自己还真捣鼓出来了,自己弄了好多的对称图这里就不晒出来了,接下来讲讲怎么做,有兴趣的同学可以自己边学边动手做,瞧瞧谁做得对称图形最好看呢。

    1. 页面设计

    要做出一个好作品,是需要熟悉对“Canvas”的操作经验的,理清好思路和制作步骤,然后设计出页面,一个页面文件代码如下

    DOCTYPE html>
    <html>
    	<head>
    		<meta charset="utf-8">
    		<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    		<title>对称图 Symmetric graphtitle>
    	head>
    	<body>
    		<canvas id="canv1" style="border: 1px solid #ccc;">canvas>
    		<img id="output_img"/>
    		<script type="module">
    			import SymmetricGraph from './symmetric_graph.js';//引入模块
    			
    			window.onload=()=>{
    				//...加载脚本
    			}
    		script>
    	body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    2. 编写脚本

    接着,写好加载脚本,代码如下,别看代码少,建议学一学,原本很多行代码就变成这样一行代码了

    const doms = {};
    ['canv1','output_img'].map(id=>[id,document.getElementById(id)]).forEach(args=>doms[args[0]]=args[1]);
    const { canv1,output_img } = doms;
    
    //创建模块对象
    let sg = new SymmetricGraph(canv1,output_img);
    //设置对象的配置
    sg.setConfig({
    	lineWidth:5,//线条宽
    	strokeStyle:'#f00',//线条颜色
    	count:7,//复制图形的数量
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    3. 编写模块

    上面发现了吗,加载的脚本中,有个对象类SymmetricGraph是哪里来的,发现缺少引用的模块文件symmetric_graph.js,接下来,我们就新建这一个模块

    1. 初始化

    模块文件的代码如下,先写好初始化逻辑,还有鼠标键的监听处理

    export default class SymmetricGraph{
    				
    	#size;
    	#ctx;
    	#ctxV;
    	#count=4;
    	
    	constructor(canv1,output_img){
    		const ctx = canv1.getContext('2d');
    		const { width, height } = ctx.canvas;
    		const size = Math.max(width,height);
    		const canvasV = document.createElement('canvas');
    		canvasV.width=size;
    		canvasV.height=size;
    		const ctxV = canvasV.getContext('2d');
    		ctx.canvas.width=size;
    		ctx.canvas.height=size;
    		//保存需要读取的设置
    		this.#size=size;
    		this.#ctx=ctx;
    		this.#ctxV=ctxV;
    		//默认设置
    		this.setConfig();
    		
    		let pointes = [];
    		//鼠标键按下时的处理
    		canv1.addEventListener('mousedown',(e)=>{
    			const { x, y } = e;
    			pointes.push({x,y});
    			ctx.beginPath();
    			ctx.moveTo(x,y);
    		});
    		//鼠标键按下并移动时的处理
    		canv1.addEventListener('mousemove',(e)=>{
    			if(pointes.length<=0) return;
    			const { x, y } = e;
    			ctx.lineTo(x,y);
    			ctx.stroke();
    			this.drawImage(ctx.canvas.toDataURL(),this.#count);
    		});
    		//鼠标键松开时的处理
    		canv1.addEventListener('mouseup',(e)=>{
    			const { x, y } = e;
    			pointes.length=0;
    		});
    	}
    	
    	//设置配置
    	setConfig(e={}){
    		const config={
    			lineWidth:2,
    			strokeStyle:'#250',
    			backgroundColor:'#fff',
    			count:4,
    		};
    		Object.assign(config,e);
    		const ctx = this.#ctx;
    		ctx.lineWidth=config.lineWidth;
    		ctx.strokeStyle=config.strokeStyle;
    		this.#ctxV.fillStyle=config.backgroundColor;
    		this.#count=config.count;
    	}
    	
    	//主要方法,绘制多个复制的图形
    	drawImage(src,count=4){
    		//...这里省略,下一步接着讲
    	}
    	
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69

    2. 主要方法

    将到重点,这是绘制图像的方法drawImage(),传入两个参数,分别时要复制的图像src,和复制数量count,仔细看下代码,会发现很简单

    let img = new Image();
    img.onload=()=>{
    	const size = this.#size;
    	const s = size*0.5;
    	const ctx = this.#ctxV;
    	const max = 360;
    	let offset = max/count;
    	//填充画布背景
    	ctx.rect(0,0,size,size);
    	ctx.fill();
    	//旋转不同角度,再绘制图形
    	for(let i=0; i<max; i+=offset){
    		ctx.save();
    		ctx.translate(size/2,size/2);
    		ctx.rotate(i/180*Math.PI);
    		ctx.translate(-size/2,-size/2);
    		ctx.drawImage(img,(size-s)/2,0,s,s);
    		ctx.restore();
    	}
    	//将绘制好的图案设置到图像标签中,显示出来
    	output_img.setAttribute('src',ctx.canvas.toDataURL());
    	//清空画布
    	ctx.clearRect(0,0,size,size);
    };
    img.src=src;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    4. 运行测试

    很快收工了,写得代码不多,没有问题的话,就用浏览器打开网页,试着在画布上用鼠标按下,随意画,就会看到生成漂亮的图案了,鼠标右键可保存下来,这个用途有很多的,能想到的是,可以用在刻印上,或者当作纹理图案素材,最后,附上录制的效果图
    在这里插入图片描述

    💡试试修改页面脚本中的如下配置,可以绘制很多不一样的图案哦

    sg.setConfig({
    	lineWidth:5,//线条宽
    	strokeStyle:'#f00',//线条颜色
    	count:7,//复制图形的数量
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
  • 相关阅读:
    OpenCV从入门到入坟
    JS Set和Map数据结构
    Spark的概念、特点、应用场景
    学好Elasticsearch系列-索引的批量操作
    【算法训练-链表 三】【判断】判断链表中是否有环、判断链表是否为回文链表
    DP/typec转VGA(国产化,工业级)
    【工具】电脑网络连接正常,但是有些页面无法登录,如何解决?
    ElementUI用el-table实现表格内嵌套表格
    泰山OFFICE技术讲座:关于文字方向的几种实现思路
    Windows上安装和配置Apache Kafka
  • 原文地址:https://blog.csdn.net/zs1028/article/details/128027780