webgl canvas系列——animation中基本旋转、平移、缩放(模拟冒泡排序过程)

文章目录

    • ⭐前言
    • ⭐canvas绘制图片
      • 💖状态保存和恢复
      • 💖移动、旋转、缩放、变形
        • 💖移动绘制一个渐变的box
        • 💖旋转
        • 💖缩放
    • ⭐模拟冒泡排序过程
    • ⭐结束

yma16-logo

⭐前言

大家好,我是yma16,本文分享webgl canvas系列——animation基本旋转、平移、缩放。
该系列往期文章
web canvas系列——快速入门上手绘制二维空间点、线、面
webgl canvas系列——快速加背景、抠图、加水印并下载图片

⭐canvas绘制图片

💖状态保存和恢复

方法作用
save()保存画布 (canvas) 的所有状态。
restore()save 和 restore 方法是用来保存和恢复 canvas 状态的,都没有参数。Canvas 的状态就是当前画面应用的所有样式和变形的一个快照。

💖移动、旋转、缩放、变形

方法作用
translate(x, y)在这里插入图片描述x *是左右偏移量,y 是上下偏移量
scale(x, y)scale方法可以缩放画布的水平和垂直的单位。两个参数都是实数,可以为负数,x 为水平缩放因子,y 为垂直缩放因子,如果比 1 小,会缩小图形,如果比 1 大会放大图形。默认值为 1,为实际大小
transform(a, b, c, d, e, f)将当前的变形矩阵乘上一个基于自身参数的矩阵

a c e b d f 0 0 1 (transform) \begin{matrix} a & c & e \\ b & d & f \\ 0 & 0 & 1 \end{matrix} \tag{transform} ab0cd0ef1(transform)

💖移动绘制一个渐变的box

使用translate移动
js代码快如下

function draw() {
    var ctx = document.getElementById("canvas").getContext("2d");
    const width=150
    const height=150
    for (var i = 0; i < 3; i++) {
      for (var j = 0; j < 3; j++) {
        ctx.save();
        ctx.fillStyle = "rgb(" + 51 * i + ", " + (255 - 51 * i) + ", 255)";
        ctx.translate(10+ j * (width+1), 10 + i * (height+1));
        ctx.fillRect(0, 0, width, height);
        ctx.restore();
      }
    }
  }

效果
translate

💖旋转

先移动原点再旋转
旋转一个正方形

  function draw() {
    const ctx = document.getElementById("canvas").getContext("2d");

    const xRectX=100
    const yRextY=100

    const width=100
    const height=100

    ctx.fillStyle = "rgba(0, 0, 200, 0.5)";
    ctx.beginPath();
    ctx.arc(xRectX, yRextY, 10, 0, Math.PI * 2, true); // 旋转中心
    ctx.fill();
    ctx.restore();
    // ctx.save();


    const translateX=xRectX+width/2
    const translateY=yRextY-height/4
  
    // left rectangles, rotate from canvas origin

    // blue rect
    ctx.fillStyle = "#0095DD";
    ctx.fillRect(xRectX, yRextY, width, height);



    ctx.fillStyle = "rgba(255, 0, 200, 0.5)";
    ctx.beginPath();
    ctx.arc(translateX, translateY, 10, 0, Math.PI * 2, true); // 旋转中心
    ctx.fill();
   
    ctx.translate(translateX, translateY); // translate back
    ctx.rotate((Math.PI / 180) * 45);
    // red rect
    ctx.fillStyle = "rgba(255,0,0,.2)";
    ctx.fillRect(0, 0, width, height);
    ctx.restore();

  }

旋转效果
蓝色的圆点移动到红色的点之后再旋转45°
rotate
移动中心 再旋转

function draw() {
    const ctx = document.getElementById("canvas").getContext("2d");

    const xRectX = 100
    const yRextY = 100

    const width = 100
    const height = 100

    ctx.fillStyle = "rgba(0, 0, 200, 0.5)";
    ctx.beginPath();
    ctx.arc(xRectX, yRextY, 10, 0, Math.PI * 2, true); // 旋转中心
    ctx.fill();
    ctx.restore();
    // ctx.save();

    // x = x + 0.5 * width
    // y = y + 0.5 * height
    const translateX = xRectX + width / 2
    const translateY = yRextY + height / 2

    // left rectangles, rotate from canvas origin

    // blue rect
    ctx.fillStyle = "#0095DD";
    ctx.fillRect(xRectX, yRextY, width, height);



    ctx.translate(translateX, translateY);
    ctx.rotate((Math.PI / 180) * 45);

    ctx.translate(-translateX, -translateY);


    // ctx.translate(translateX, translateY); // translate back

    // red rect
    ctx.fillStyle = "rgba(255,0,0,.2)";
    ctx.fillRect(xRectX, xRectX, width, height);


    ctx.fillStyle = "rgba(255, 0, 200, 0.5)";
    ctx.beginPath();
    ctx.arc(translateX, translateY, 10, 0, Math.PI * 2, true); // 旋转中心
    ctx.fill();

}

效果(红点为旋转中心)
rate_center

💖缩放

缩放文字

function draw() {
    var ctx = document.getElementById("canvas").getContext("2d");
    // mirror horizontally
    ctx.scale(2, 2);
    ctx.font = "48px serif";
    ctx.fillStyle = "rgba(0, 0, 200, 0.5)";
    ctx.fillText("csdn yma16", 0, 120);
  }

scale

⭐模拟冒泡排序过程

冒泡排序(Bubble Sort)
是一种计算机科学领域的较简单的排序算法。
它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行,直到没有相邻元素需要交换,也就是说该元素列已经排序完成。

vue3页面简单使用canvas模拟冒泡排序的效果

<script lang="js" setup>
import { reactive, onMounted } from 'vue';
const state = reactive({
    value: '[100,20,69,16,55,33]',
    title: '冒泡排序可视化',
    visualSortArray: [

    ]
})


function bubbleSort(arr) {
    // 冒泡排序算法,对数组进行排序,同时记录每一步操作,保存在一个数组中
    function sort() {
        // virtualArr 用来存放 每一个步内容的数组
        const virtualArr = [arr.slice()];
        console.log('virtualArr', virtualArr)
        const max = arr.length;
        for (let i = 0; i < max; i++) {
            let done = true;
            for (let j = 0; j < max - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    let temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                    done = false;
                    virtualArr.push(arr.slice());
                }
            };
            if (done) {
                break;
            };
        }
        return virtualArr;
    }

    // 绘画,调用一次就画出一步的图像 
    function darw(arr, count) {
        const canvas = document.getElementById('myCanvas');
        const ctx = canvas.getContext('2d');
        
        // 最大高度 400
        let maxHeight = canvas.height;
        // 每个长方形的宽度
        let width = 20;
        // 每个长方形之间的间隔
        let space = 100;

        const total = arr.reduce((p, c) => p + c, 0)

        // 清空画布
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        // 设置字体
        ctx.font = "18px serif";
        // 在页面上,画出一步的内容
        for (let i = 0; i < arr.length; i++) {
            ctx.fillStyle = '#61C5FE';

            const x= i * (width + space)
            const y= maxHeight - arr[i]
            const height=Math.round((arr[i] / total)*100  + 100)
            ctx.fillRect(x, y, width, height);
            console.log('x',x)
            console.log('y',y)
            console.log('width',width)
            console.log('height',height)
            ctx.fillStyle = '#240be4';
            // 标题文字
            ctx.fillText(arr[i], x, y);
            ctx.restore();
        }

        ctx.fillText(`${count}趟排序`, 200, 100);


        ctx.fillStyle = "rgba(0, 66, 200, 0.5)";
        ctx.beginPath();
        ctx.lineTo(0, 400);
        ctx.lineTo(800, 400);
        ctx.stroke()
    }

    // 动画 
    function animation() {
        // 调用sort 方法,返回包括每一步内容的数组
        var virtualArr = sort();
        var interval = 500;
        // 遍历得到的数组,每隔500ms,调用darw 方法,画出一步内容
        virtualArr.forEach((item, index) => {
            setTimeout(() => darw(item, index + 1), index * interval);
        });

        state.visualSortArray = virtualArr
    }

    animation();
}




const sortBtn = () => {

    const arr = state.value.replace('[', '').replace(']', '').split(',').map(n => +n)
    console.log('arr', arr)
    bubbleSort(arr);
}

onMounted(()=>{
    sortBtn()
})



</script>
<template>
    <div>

        <div style="display:flex;">
            <a-card :title="state.title" style="min-width: 800px">
                <div class="input-box">

                    <div>
                        <a-input v-model:value="state.value" placeholder="请输入数组" clearable></a-input>
                    </div>
                    <div style="margin-left:50px"><a-button type="primary" @click="sortBtn">开始排序</a-button></div>
                </div>
                <div class="container-sort">
                    <div style="text-align: right;margin-right: 20px;">
                        <div v-for="(item, index) in state.visualSortArray" :key="index">
                            <div>
                                第 {{ index + 1 }} 躺排序:  {{ item.toString() }}
                            </div>
                        </div>
                    </div>

                    <canvas id="myCanvas" width="800" height="400"> </canvas>
                </div>

            </a-card>
        </div>

    </div>
</template>

<style lang="less">
.input-box {
    display: flex;
    margin-bottom: 10px;
}

.container-sort {
    height: 800px;
    border: 1px solid #dcdcdc;
}

.box {
    margin: 10px;

    .bar {
        width: 10px;
        background: #1677ff;
        border-radius: 2px;
    }

    .num {
        font-size: 18px;
    }
}
</style>

效果
sort
inscode代码块

⭐结束

本文分享到这结束,如有错误或者不足之处欢迎指出!
light

👍 点赞,是我创作的动力!
⭐️ 收藏,是我努力的方向!
✏️ 评论,是我进步的财富!
💖 最后,感谢你的阅读!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/565163.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【MySQL 数据宝典】【磁盘结构】- 002 数据字典

一、数据字典 ( Data Dictionary ) 1.1 背景介绍 我们平时使用 INSERT 语句向表中插入的那些记录称之为用户数据&#xff0c;MySQL只是作为一个软件来为我们来保管这 些数据&#xff0c;提供方便的增删改查接口而已。但是每当我们向一个表中插入一条记录的时候&#xff0c;MyS…

周鸿祎和雷军、马化腾相逢一笑泯恩仇

关注卢松松&#xff0c;会经常给你分享一些我的经验和观点。 马云竟然没有到场&#xff0c;真是遗憾! 前两天工信部和互联网协会联合举办的中国互联网三十周年座谈会上。周鸿祎、雷军、马化腾相逢一笑泯恩仇。 第一条视频&#xff1a; 周鸿祎和马化腾握手言欢&#xff0c…

Mendix是谁?作为致力于企业低代码服务平台的领头羊,它解决了哪些问题?

一、Mendix 成立的背景 Mendix的成立是为了解决软件开发中最大的问题&#xff1a;业务和IT之间的脱节。这一挑战在各个行业和地区都很普遍&#xff0c;很简单&#xff1a;业务需求通常被描述为IT无法正确解释并转化为软件。业务和IT之间缺乏协作的原因是传统的代码将开发过程限…

Vue.js前端开发零基础教学(六)

学习目标 了解什么是路由&#xff0c;能够说出前端后端路由的原理 掌握多种路由的使用方法&#xff0c;能够实现路由的不同功能 掌握Vue Router的安装及基本使用方法 5.1 初始路由 提到路由&#xff08;Route),一般我们会联想到网络中常见的路由器&#xff08;Router),…

30 消息队列

原理 操作系统可以通过页表映射在共享区创建一块共享内存&#xff0c;也可以申请一个队列。A进程和B进程可以向这个队列发送数据块&#xff0c;两个进程接收数据块来通信 函数 申请数据块 参数中的key来自于ftok函数 删除消息队列 同样消息队列也有数据结构管理&#xff…

c#学习入门1

一、环境配置 颜色主题 字体设置 行号设置 二、第一个应用程序 1. 在解决方案下创建一个新项目 第一种注释&#xff1a;两杠注释 第二种注释&#xff1a;星号注释 第三种注释&#xff1a;三杠注释(只有在花括号后面输出才会自动补全&#xff09; 2.控制台输入打印基础语句 输…

java在线问卷调查系统的设计与实现(springboot+mysql源码+文档)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的在线问卷调查系统。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 基于java的在线问卷调查…

HBM:小贵但AI需要

即将推出的高带宽内存 high-bandwidth memory在散热方面还存在挑战&#xff0c;但可能即将得到改善。 高带宽内存 &#xff08;HBM&#xff09; 正在成为算力提供商的首选内存&#xff0c;由于 AI/ML 的需求&#xff0c;使用量也在继续增长&#xff0c;HBM 提供紧凑的 2.5D 外形…

P1024 [NOIP2001 提高组] 一元三次方程求解

题目描述&#xff1a; AC代码&#xff1a; #include<iostream>using namespace std;double a,b,c,d; int ans 0;double f(double x) {return a * x * x * x b * x * x c * x d; }int main() {scanf("%lf %lf %lf %lf",&a,&b,&c,&d);for…

钉钉报警的优势在哪里?如何配置钉钉机器人进行报警信息推送?

一、常见的报警方式 1、短信或者电话报警 这样的报警方式更适合高级别的报警提醒&#xff0c;用于处理紧急情况。出现级别不高而又频繁地发送短信会让人产生排斥感&#xff0c;而且电话或者短信的报警方式也存在一定的成本。 2、邮件报警 邮件报警更适用于工作时的提醒&…

DSSM 模型技术介绍

转自&#xff1a;git 本文属于新闻推荐实战-召回阶段-DSSM召回模型。区别于策略召回&#xff0c;基于向量召回也是目前工业界常用的一种召回方法。这里我们将介绍一个比较经典的召回模型DSSM&#xff0c;希望读者可以快速掌握模型原理以及细节&#xff0c;同时可以了解具体的实…

第25天:安全开发-PHP应用文件管理包含写入删除下载上传遍历安全

第二十五天 一、PHP文件管理-下载&删除功能实现 1.文件上传&#xff1a; 无过滤机制黑名单过滤机制白名单过滤机制文件类型过滤机制 2.文件删除&#xff1a; unlink() 文件删除函数调用命令删除&#xff1a;system shell_exec exec等 3. 文件下载&#xff1a; 修改HT…

问题带来多少成长,看你挖得有多深多痛

原文: 一次Redis访问超时的“捉虫”之旅 力是相互的&#xff0c;成长与痛苦也是相互的。 01-引言 最近在对一个老项目使用的docker镜像版本升级过程中碰到一个奇怪的问题&#xff0c;发现项目升级到高版本镜像后&#xff0c;访问Redis会出现很多超时错误&#xff0c;而降回之…

stable diffusion Temporal-kit和EbSynth视频转动画学习笔记

1、打开stable diffsuion webui 点击Temporal-kit 页签&#xff0c;再点击预处理pre-processing,上传视频 在工作目录下得到拆分的关键帧,在input目录里 打开图生图&#xff0c;输入正反描述词&#xff0c;其他配置如下 批量生成图片&#xff0c;找到最满意的那一张&#xff0…

如何判别三角形和求10 个整数中最大值?

分享每日小题&#xff0c;不断进步&#xff0c;今天的你也要加油哦&#xff01;接下来请看题------> 一、已知三条边a&#xff0c;b&#xff0c;c能否构成三角形&#xff0c;如果能构成三角形&#xff0c;判断三角形的类型&#xff08;等边三角形、等腰三角形或普通三角形 …

【Interconnection Networks 互连网络】Torus 网络拓扑

1. Torus 网络拓扑2. Torus 网络拓扑结构References 1. Torus 网络拓扑 Torus 和 Mesh 网络拓扑&#xff0c;又可以称为 k-ary n-cubes&#xff0c;在规则的 n 维网格中包裹着 N k^n 个节点&#xff0c;每个维度都有 k 个节点&#xff0c;并且最近邻居之间有通道。k-ary n-c…

数据可视化(八):Pandas时间序列——动态绘图,重采样,自相关图,偏相关图等高级操作

Tips&#xff1a;"分享是快乐的源泉&#x1f4a7;&#xff0c;在我的博客里&#xff0c;不仅有知识的海洋&#x1f30a;&#xff0c;还有满满的正能量加持&#x1f4aa;&#xff0c;快来和我一起分享这份快乐吧&#x1f60a;&#xff01; 喜欢我的博客的话&#xff0c;记得…

关于杰理AC695蓝牙模式下按键处理函数处理

一、杰理蓝牙模式下又分为SYS_KEY_EVENT和SYS_BT_EVENT。SYS_KEY_EVEN主要是对按键的控制事件&#xff0c;SYS_BT_EVENT是蓝牙模式协议栈状态事件、hci事件、对箱事件。 二、按键通过key_event *key &event->u.key; u定义了一个union事件的联合体&#xff0c;通过按键k…

【C++ STL序列容器】array 数组

文章目录 【 1. 基本原理 】【 2. array 的创建 】2.1 不赋初值2.2 赋默认值2.3 赋指定值 【 3. array 的成员函数 】实例 【 1. 基本原理 】 array 是在 C 普通数组的基础上添加了一些成员函数和全局函数。在使用上&#xff0c;它 比普通数组更 安全&#xff0c;且效率并没…

Web3钱包开发获取测试币-Base Sepolia(二)

Web3钱包开发获取测试币-Base Sepolia(二) ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/b0c0ac86b04a496087471388532bc54a.png) 基于上篇 Web3钱包开发获取测试币-Polygon Mumbai(一) &#xff1a;https://suwu150.blog.csdn.net/article/details/137949473 我…