iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >使用Canvas怎么实现一个图片分割效果
  • 854
分享到

使用Canvas怎么实现一个图片分割效果

2023-06-09 13:06:17 854人浏览 安东尼
摘要

本篇文章为大家展示了使用canvas怎么实现一个图片分割效果,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。首先我们要初始化一些变量,比如图片的宽高,矩形的个数,剪切的尺寸等,然后再计算每个矩形的坐标

本篇文章为大家展示了使用canvas怎么实现一个图片分割效果,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

首先我们要初始化一些变量,比如图片的宽高,矩形的个数,剪切的尺寸等,然后再计算每个矩形的坐标,使用一个二重循环将矩形坐标保存在data中。每个矩形有个随机位移,这个位移也需要保存起来,存在randoms中。其中x,y表示canvas画布的坐标,x1,y1表示图片裁剪的坐标。

init: function (context, width, height, area, img) {            this.context = context;            this.img = img;            this.imgWidth = img[0].width;          //图片宽高            this.imgHeight = img[0].height;            this.index = 0;                       //当前图片序号            this.width = width;                  //画布宽高            this.height = height;            this.area = height/12;                     //小矩形长度            this.countX = width / this.area;             //水平和垂直方向小矩形个数            this.countY = height / this.area;            this.wx = this.imgWidth / this.countX;      //图片在小矩形中的宽高            this.wy = this.imgHeight / this.countY;            this.state = true;                   //图片状态,true表示未拆分            this.dataFlag = true;                //小矩形坐标状态,true表示未加上随机值            this.duration = 1000;                 //动画时间            this.duration2 = 1500;            this.startTime = 0;            this.data = [];                       //小矩形坐标信息            this.randoms = [];                    //位置随机值            //初始化矩形坐标            var x1 = 0, y1 = 0, x = 0, y = 0;            for (var i = 0; i < this.countY; i++) {                for (var j = 0; j < this.countX; j++) {                    context.drawImage(this.img[this.index], x1, y1, this.wx, this.wy, x, y, this.area, this.area);                    //储存矩形坐标                    this.data.push({                        x1: x1,                        y1: y1,                        x: x,                        y: y                    });                    //添加随机值                    this.randoms.push(random(-this.area, this.area));                    x1 += this.wx;                    x += this.area;                }                x1 = 0;                y1 += this.wy;                x = 0;                y += this.area;            }            this.checkMargin();        }

检测边缘

在给矩形添加位移之前我们需要判断一下位移后的坐标是否超过图片界限,比如在顶部的矩形如果是y轴移动,那么只能够向上移,判断的条件为当前坐标加上位移值是否小于0或大于图片的宽高。如果更新后的坐标小于0,那么这个随机值一定是负数,需要把随机值改为正数,如果大于图片高度,那么改成负数即可。由于每个矩形的移动都是在一个方向上移动,所以我这里写成偶数位移动x轴,奇数位移动y轴。

//检测边缘        checkMargin: function () {            var self = this;            this.data.forEach(function (item, index) {                if (index % 2 == 0) {  // 下标为2的倍数时移动x轴,否则移动y轴                    if ( item.x1 + self.randoms[index] < 0)                        // 改为正数                        self.randoms[index] = -self.randoms[index];                    if (item.x1 + self.wx + self.randoms[index] > self.imgWidth )                        // 改为负数                        self.randoms[index] = -Math.abs(self.randoms[index])                } else {                    if (item.y1 + self.randoms[index] < 0)                        self.randoms[index] = -self.randoms[index];                    if (item.y1 + self.randoms[index] + self.wy > self.imgHeight)                        self.randoms[index] = -Math.abs(self.randoms[index])                }            })        }

分离和复原

动画的内容的分离和复原就是更新矩形坐标的值,打乱内容只要将data里的坐标加上随机值,而复原就是减去随机值,

//检测边缘        checkMargin: function () {            var self = this;            this.data.forEach(function (item, index) {                if (index % 2 == 0) {  // 下标为2的倍数时移动x轴,否则移动y轴                    if ( item.x1 + self.randoms[index] < 0)                        // 改为正数                        self.randoms[index] = -self.randoms[index];                    if (item.x1 + self.wx + self.randoms[index] > self.imgWidth )                        // 改为负数                        self.randoms[index] = -Math.abs(self.randoms[index])                } else {                    if (item.y1 + self.randoms[index] < 0)                        self.randoms[index] = -self.randoms[index];                    if (item.y1 + self.randoms[index] + self.wy > self.imgHeight)                        self.randoms[index] = -Math.abs(self.randoms[index])                }            })        }

在储存好坐标后就可以去实现平移动画了,移动的过程有一个平滑的过渡,我们可以使用Tween.js的缓动算法,该算法有4个参数分别是当前时间,初始位置,结束位置,动画时间。详细内容可以参考张鑫旭的这篇文章https://www.zhangxinxu.com/Wordpress/2016/12/how-use-tween-js-animation-easing/ 。通过Tween.js可以算出每一帧要移动的距离,然后再使用requestAnimationFrame去更新坐标。

blockAnimation: function () {            var flag = 1;            if (this.state) {  // 判断是打乱图片还是还原图片                this.update(true)            } else {                flag = -1;                this.update(false);            }            var self = this;            this.startTime = +new Date();  // 获取当前时间            this.state = !this.state;            (function animation() {                var t = +new Date();                if (t >= self.startTime + self.duration) {  // 动画结束条件                    return false;                }                self.data.forEach(function (item, index) {                    if (index % 2 == 0) {                        var pos = Math.tween.Expo.easeInOut(t - self.startTime, 0, self.randoms[index] * flag, self.duration);   // 计算出每帧移动的距离                        self.context.drawImage(self.img[self.index], item.x1 + pos, item.y1, self.wx, self.wy, item.x, item.y, self.area, self.area);                    } else {                        var pos = Math.tween.Expo.easeInOut(t - self.startTime, 0, self.randoms[index] * flag, self.duration);                          self.context.drawImage(self.img[self.index], item.x1, item.y1 + pos, self.wx, self.wy, item.x, item.y, self.area, self.area);                    }                });                requestAnimationFrame(animation);            })();        }

到这里就已经实现了分离和复原的动画了

使用Canvas怎么实现一个图片分割效果

图片切换

接下来开始处理图片切换的部分,这里跟轮播图有点像,轮播图动画是将每个图片位置移动可视窗口宽度的距离,这里也是一样,只要将坐标加上图片高度就可以实现y轴上的切换。和轮播图不一样的是,我们这里只有一个canvas标签,在切换时只需要改变当前图和下一张图的坐标,当前图移动距离为y1 + pos,下张图移动距离为y1 + pos - imgHeight(为什么要减imgHeight就不用说了吧)。

//垂直滑动动画        verticalAnimation: function (val) {            if (!this.time2) {                return false;            }            this.checkTime(2);            var self = this;            val ? val = 1 : val = -1;  //判断上滑还是下滑            if ((this.index + val) < 0 || (this.index + val) >= (this.img.length)) {   //判断图片序号是否到底                return false;            }            this.state ? this.update(true) : this.update(false);            this.startTime = +new Date();            (function animation() {                var t = +new Date();                if (t >= self.startTime + self.duration2) {                    val === 1 ? self.index++ : self.index--;  //调整图片顺序                    self.index < 0 ? self.index = self.img.length - 1 : self.index;                    self.index >= self.img.length ? self.index = 0 : self.index;                    return false;                }                self.data.forEach(function (item) {                    var pos = Math.tween.Cubic.easeInOut(t - self.startTime, 0, (self.imgHeight) * val, self.duration2);                    // 更新当前图片坐标                    self.context.drawImage(self.img[self.index], item.x1, item.y1 + pos, self.wx, self.wy, item.x, item.y, self.area, self.area);                    // 更新下张图片坐标                    self.context.drawImage(self.img[self.index + val], item.x1, item.y1 + pos - self.imgHeight * val, self.wx, self.wy, item.x, item.y, self.area, self.area);                });                requestAnimationFrame(animation);            })()        }

上述内容就是使用Canvas怎么实现一个图片分割效果,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注编程网精选频道。

--结束END--

本文标题: 使用Canvas怎么实现一个图片分割效果

本文链接: https://www.lsjlt.com/news/256001.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C++ 生态系统中流行库和框架的贡献指南
    作为 c++++ 开发人员,通过遵循以下步骤即可为流行库和框架做出贡献:选择一个项目并熟悉其代码库。在 issue 跟踪器中寻找适合初学者的问题。创建一个新分支,实现修复并添加测试。提交...
    99+
    2024-05-15
    框架 c++ 流行库 git
  • C++ 生态系统中流行库和框架的社区支持情况
    c++++生态系统中流行库和框架的社区支持情况:boost:活跃的社区提供广泛的文档、教程和讨论区,确保持续的维护和更新。qt:庞大的社区提供丰富的文档、示例和论坛,积极参与开发和维护。...
    99+
    2024-05-15
    生态系统 社区支持 c++ overflow 标准库
  • c++中if elseif使用规则
    c++ 中 if-else if 语句的使用规则为:语法:if (条件1) { // 执行代码块 1} else if (条件 2) { // 执行代码块 2}// ...else ...
    99+
    2024-05-15
    c++
  • c++中的继承怎么写
    继承是一种允许类从现有类派生并访问其成员的强大机制。在 c++ 中,继承类型包括:单继承:一个子类从一个基类继承。多继承:一个子类从多个基类继承。层次继承:多个子类从同一个基类继承。多层...
    99+
    2024-05-15
    c++
  • c++中如何使用类和对象掌握目标
    在 c++ 中创建类和对象:使用 class 关键字定义类,包含数据成员和方法。使用对象名称和类名称创建对象。访问权限包括:公有、受保护和私有。数据成员是类的变量,每个对象拥有自己的副本...
    99+
    2024-05-15
    c++
  • c++中优先级是什么意思
    c++ 中的优先级规则:优先级高的操作符先执行,相同优先级的从左到右执行,括号可改变执行顺序。操作符优先级表包含从最高到最低的优先级列表,其中赋值运算符具有最低优先级。通过了解优先级,可...
    99+
    2024-05-15
    c++
  • c++中a+是什么意思
    c++ 中的 a+ 运算符表示自增运算符,用于将变量递增 1 并将结果存储在同一变量中。语法为 a++,用法包括循环和计数器。它可与后置递增运算符 ++a 交换使用,后者在表达式求值后递...
    99+
    2024-05-15
    c++
  • c++中a.b什么意思
    c++kquote>“a.b”表示对象“a”的成员“b”,用于访问对象成员,可用“对象名.成员名”的语法。它还可以用于访问嵌套成员,如“对象名.嵌套成员名.成员名”的语法。 c++...
    99+
    2024-05-15
    c++
  • C++ 并发编程库的优缺点
    c++++ 提供了多种并发编程库,满足不同场景下的需求。线程库 (std::thread) 易于使用但开销大;异步库 (std::async) 可异步执行任务,但 api 复杂;协程库 ...
    99+
    2024-05-15
    c++ 并发编程
  • 如何在 Golang 中备份数据库?
    在 golang 中备份数据库对于保护数据至关重要。可以使用标准库中的 database/sql 包,或第三方包如 github.com/go-sql-driver/mysql。具体步骤...
    99+
    2024-05-15
    golang 数据库备份 mysql git 标准库
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作