React + Leafer + AnimeJS实现电影胶片效果

起初是想做个视频有电影胶片的效果,本来计划这用PR来做,但是PR不太会,所以用自己的专业来搞一个好了。

电影胶片效果主要分为三部分: 1、胶片的边框,2、展示的内容,3、电影胶片的播放。因为需要绘制的元素比较多,这里使用 Leafer(一个不错的 Canvas 库) 来进行绘制,播放效果使用 animejs 动画库来进行处理。

绘制底版

底版的绘制就是一个黑色的长方形矩形,矩形的宽高 = 图片的宽高 + 边框的宽高。然后通过在上面绘制白色的方格使其达到胶片效果。代码示例如下:

ts 复制代码
const leafer = new Leafer({
	view: document.getElementById("video"),
	type: "user",
});

const border = new Rect({
	x: 0,
	y: 0,
	width: canvasWidth,
	height: 400,
	fill: "#000000",
});
leafer.add(border);

绘制边框

1、绘制顶部边框

根据图例可以得出顶部边框的起点坐标:

x = 边距 + 单元格宽度 + 边距 ; y = 边距 + 单元格高度 + 边距

顶部需要绘制多少个方块由需要展示的图片数量来决定的。

顶部方格数量 = 图片数量 * 每张图片宽度需要的方格

每张图片宽度需要的方格 = (图片宽度 + 边距) / (方格宽度 + 边距)

因为是在顶部,所以只需要计算方格横向的偏移量。

代码示例如下:

ts 复制代码
for (let i = 0; i < num * singleImgHorizontalCellNum; i++) {
	const x = margin + (width + margin) * (i + 1);
	const y = margin;
	const topCell = new Rect({
		x,
		y,
		width,
		height,
		fill: "#ffffff",
	});

	leafer.add(topCell);
}

2、绘制底部边框

底部边框与顶部边框的纵向坐标不同,其他的保持一致。

纵向坐标 = 顶部边框高度 + 图片高度 + 边距。

代码示例如下:

ts 复制代码
for (let i = 0; i < num * singleImgHorizontalCellNum; i++) {
	const x = margin + (width + margin) * (i + 1);
	const y = margin + height + margin + imgHeight + margin;
	const topCell = new Rect({
		x,
		y,
		width,
		height,
		fill: "#ffffff",
	});

	leafer.add(topCell);
}

3、绘制左侧边框

根据图例可知,左侧边框的起点坐标 X = margin; y = margin

左侧边框需要绘制的单元格 = (顶部边框的高度 + 图片的高度 + 底部边框的高度) / (方格的高度 + 边距)

因为是纵向绘制,所以横向坐标都是相同的,代码示例如下:

ts 复制代码
const verticalCellNum =
	(margin + height + margin + imgHeight + margin + height) / (height + margin);
for (let i = 0; i < verticalCellNum; i++) {
	const x = margin;
	const y = margin + (height + margin) * i;
	const topCell = new Rect({
		x,
		y,
		width,
		height,
		fill: "#ffffff",
	});
	leafer.add(topCell);
}

4、绘制右侧边框

右侧边框的绘制与左侧是基本相同,需要修改左侧横向的坐标。

右侧横向的坐标 = 左侧边框的宽度 + (图片的宽度 + 边距) * 图片的数量

代码示例如下:

ts 复制代码
for (let i = 0; i < verticalCellNum; i++) {
	const x =
		margin +
		width +
		margin +
		singleImgHorizontalCellNum * (width + margin) * num;
	const y = margin + (height + margin) * i;
	const topCell = new Rect({
		x,
		y,
		width,
		height,
		fill: "#ffffff",
	});
	leafer.add(topCell);
}

内容填充

1、使用 Rect 进行占位

由图例可知,Rect 的开始坐标:X = 顶部边框的高度 Y = 左侧边框的宽度

代码示例如下:

ts 复制代码
for (let i = 0; i < num; i++) {
	const x = margin + width + margin + (imgWidth + margin) * i;
	const y = margin + height + margin;
	const topCell = new Rect({
		x,
		y,
		width: imgWidth,
		height: imgHeight,
	});

	leafer.add(topCell);
}

2、使用图片进行填充

leafer 支持 rect 使用图片进行填充,为了简化代码,这里把图片的名称修改为数字,上述代码修改如下:

ts 复制代码
for (let i = 0; i < num; i++) {
	const x = margin + width + margin + (imgWidth + margin) * i;
	const y = margin + height + margin;

	const topCell = new Rect({
		x,
		y,
		width: imgWidth,
		height: imgHeight,
		fill: {
			type: "image",
			url: `/src/assets/images/${i + 1}.jpg`,
		},
	});

	leafer.add(topCell);
}

至此,静态的电影胶片效果就完成了。接下来需要让胶片能够动起来。

胶片播放

这里使用 animejs 来处理胶片的移动,让画布的左侧向左移动直至移动整个画布的宽度。代码示例如下:

ts 复制代码
anime({
	targets: "#video",
	translateX: -canvasWidth,
	duration: 60 * 1000,
	easing: "easeInOutQuad",
});

通过 duration 可以设置移动完成的时间,easing 可以设置移动的动画,这里使用的是先缓慢移动,后加速,快结束时减速的动画效果。

至此,电影胶片播放效果就完成了。

代码地址

stackblitz.com/edit/vitejs...

相关推荐
玩电脑的辣条哥3 小时前
Python如何播放本地音乐并在web页面播放
开发语言·前端·python
ew452183 小时前
ElementUI表格表头自定义添加checkbox,点击选中样式不生效
前端·javascript·elementui
suibian52353 小时前
AI时代:前端开发的职业发展路径拓宽
前端·人工智能
画月的亮3 小时前
element-ui 使用过程中遇到的一些问题及解决方法
javascript·vue.js·ui
Moon.93 小时前
el-table的hasChildren不生效?子级没数据还显示箭头号?树形数据无法展开和收缩
前端·vue.js·html
m0_526119403 小时前
点击el-dialog弹框跳到其他页面浏览器的滚动条消失了多了 el-popup-parent--hidden
javascript·vue.js·elementui
垚垚 Securify 前沿站3 小时前
深入了解 AppScan 工具的使用:筑牢 Web 应用安全防线
运维·前端·网络·安全·web安全·系统安全
工业甲酰苯胺6 小时前
Vue3 基础概念与环境搭建
前端·javascript·vue.js
lyj1689976 小时前
el-tree选中数据重组成树
javascript·vue.js·elementui
mosquito_lover17 小时前
怎么把pyqt界面做的像web一样漂亮
前端·python·pyqt