文章目录
- 弧形选项卡
- 瀑布流布局
- 手写钉钉动画
- 鼠标移动的高亮边框效果
- 头像超出边框特效
- 透明盒子的渐变阴影(clip-path)
- 图片3D_Hover倾斜
- 图片3D突显效果
- 图片9宫格效果
- 图片锯齿菱形边缘(mask)
- 图片轮播(不无限循环,思路教学)
- 图片上下视差滚动
- 图片旋转视差效果
- 文字标题丝滑动画
- 文字交错排列
- 文字交融展开
- 文字连续光影效果
- 文字镂空
- 文字下划线动画
- 文字自动适配背景
- 下拉菜单过渡效果
- 圆形放大的hover效果
- animation-delay实现动画
- canvas 常用方法
- canvas 处理图片
- canvas画随机树
- canvas获取视频帧
- canvas阴影画出图片
- canvas粒子时钟
- canvas动画(点+线)
- svg描边动画 (通用)
- svg实现按钮故障波纹
- svg实现文字适应纹理(无效,求助)
最近菜鸟没来写文章,一是因为被一些bug搞得焦头烂额,二是因为在查漏补缺,感觉自己太菜了,感觉收藏的很多,但是会的很少。
所以菜鸟就把收藏的渡一的教程都刷了一遍,能写代码的就写了,要记的就准备每天都看,感觉渡一的短视频确实不错!但是长视频质量感觉不咋地,反正之前花钱买了几个做活动的课,长的视频就讲得没有短视频好了!
这是我学习的一些成果,代码已经上传到 GitHub 了,感兴趣的可以来看看:github
下面就是我实现的一些效果,代码什么的都在 GitHub 上,注释也很详细,所以这里就展示效果了!
弧形选项卡
弧形选项卡
其实这是一个长方形设置了上方的border-radius,旁边两个是伪元素,是正方形减去两个半圆(锥型渐变),然后通过旋转得到的!
瀑布流布局
瀑布流布局
这里的思路就是循环创建图片元素,在图片 onload 之后,设置每个图片的定位!
定位就是要根据图片宽度,看整个屏幕有多少列 + 间隙多大,并根据列数生成一个记录高度的数组(一开始都为0),每次选择最短的列加上图片,并根据图片高度,设置数组数据+父元素高度(因为定位不会撑大父元素)!
手写钉钉动画
手写钉钉动画
这里的思路可以看我的博客:前端三件套配合MarsCode实现钉钉官网动画 # 豆包MarsCode
鼠标移动的高亮边框效果
鼠标移动的高亮边框效果
这里的思路就是使用三层实现,边框其实是父元素背景色,内容是子元素缩小一点在父元素里面居中,而高亮就是子元素的 before伪元素,伪元素设置成圆形渐变并根据鼠标位置设置偏移量就行了!
头像超出边框特效
头像超出边框特效
这个效果一开始看见以为很简单,但是其实有点难,因为边框会被头像盖住,这里没有用渡一的思路,感觉太复杂了,这是菜鸟自己的思路写的!
菜鸟设置了两个容器,把父容器设置得高一点,子容器放到父容器的底部,就可以做到下面超出隐藏,上面不隐藏了,然后边框就是用伪元素设置的,不能使用 border,会被 img挡住!
透明盒子的渐变阴影(clip-path)
透明盒子的渐变阴影(clip-path)
这里大家一看可能会感觉很简单,直接用一个白色的盒子,放在一个渐变的盒子上不就行了?
但是这里不一样,这里的内容里面是没设置背景色的,也可以实现该效果,具体使用的是背景裁剪!
裁剪思路
图片3D_Hover倾斜
图片3D_Hover倾斜
这里的盒子阴影看起来像渐变,其实不是,和上面的效果没有关系,这里就是简单的设置了四个方向的纯色 box-shadow
.card:hover {
box-shadow: -3px -3px 10px #a1f541, 3px 3px 10px #f1597a,
-3px 3px 10px #a1f541, 3px -3px 10px #f1597a;
}
这里主要是鼠标移入后改变 css变量,去设置图片的 transform !
图片3D突显效果
图片3D突显效果
这里就是纯css效果了,和上面没关系,不用跟随鼠标改变偏移量!
就是人物元素一开始看不见,hover 后设置可见并设置 transform,卡片和文字也是设置移入就 transform!
图片9宫格效果
图片9宫格效果
这里的思路很巧妙,没有用到 js,就纯css 实现的,巧妙的就在于 css 后面的会覆盖前面的,然后通过 列和行 的选择,依次设置好了全部图片的偏移量,用scss可能很简单,但是纯css 能想到很难!
.imgItem {
width: 200px;
height: 200px;
background-image: url(../img/11.png);
background-size: 600px 600px;
/* 鼠标划入的偏移 */
position: relative;
transition: all 0.3s;
}
/* n 的有关问题见 问题img */
/* 第一列 */
.imgItem:nth-child(3n + 1) {
left: -20px;
background-position-x: 0;
}
/* 第二列 */
.imgItem:nth-child(3n + 2) {
left: 0;
background-position-x: -200px;
}
/* 第三列 */
.imgItem:nth-child(3n) {
left: 20px;
background-position-x: -400px;
}
/* 选横着的不好选,取巧办法 */
/* 1-9 会被 1-6 覆盖,1-6 会被 1-3 覆盖 */
/* 注意 n 的位置不能乱放,见:问题img */
.imgItem {
top: 20px;
background-position-y: -400px;
}
.imgItem:nth-child(-n + 6) {
top: 0;
background-position-y: -200px;
}
.imgItem:nth-child(-n + 3) {
top: -20px;
background-position-y: 0;
}
图片锯齿菱形边缘(mask)
图片锯齿菱形边缘(mask)
这里设置的思路很难,反正主要是:使用锥形渐变实现一个一个小方块,然后使用线性渐变旋转设置出菱形,再通过mask蒙版显示菱形加小方块,最后背景裁剪,把多余的小方块去掉!
只能说这里菜鸟并不能举一反三,这种还是太牛了!
图片轮播(不无限循环,思路教学)
图片轮播(不无限循环,思路教学)
轮播是前端特效过不去的坎,这里我照着渡一也只学到了不无限循环的思路,循环确实不知道咋搞,只知道要复制元素,但是不知道咋复制,这个感兴趣的读者可以实现了留言,感谢!
反正思路一般就是这样:
- 获取轮播的图片
- 设置一个变量记录当前图片索引(表示当前显示的第几张)
- 根据当前的索引设置布局(暂不写,整个轮播就是完成这个函数)–> 除了这个基本都是通用的
- 获取两个按钮
- 按钮添加事件
- 添加点击轮播图事件
其中3就是要循环图片元素,针对每个图片按照需求设置样式就行了。
图片上下视差滚动
图片上下视差滚动
这里的思路就是,先写出css,能通过添加class 实现上下滚动的效果!然后就是设置index,并通过index 每次都准备三个元素,前一张、当前一张、后一张,然后监听鼠标滚动,实时的去修改index,等transitionend 事件结束就移除加的class就行!
图片旋转视差效果
图片旋转视差效果
这里就是使用grad布局,然后让其旋转,而里面的图片反向旋转就行了!
需要学习的是,当动画是类似的时候,只是方向、角度等不一样,完全可以使用css 变量,共用同一个动画
/* 动画 */
.container {
--r: 360deg;
}
.item img {
--r: -360deg;
}
@keyframes ratation {
to {
transform: rotate(var(--r));
}
}
文字标题丝滑动画
文字标题丝滑动画
只要搞定一个文字的运动,其他的都延时就行了!
p 元素内容转成 span
这里主要是要学会将 p 元素内容转成 span !
const pArr = document.querySelectorAll(".title");
let time = 0;
for (let i of pArr) {
// 将 p 转成 span 通用函数
i.innerHTML = i.textContent
.split("")
.map((e, i, arr) => {
// console.log(time);
time = time + 0.2;
return `<span style='--delay:${time}s'>${e}</span>`;
})
.join("");
}
连续阴影
连续阴影
/* 不能直接设置6px,会分离 */
text-shadow: 1px 1px #333, 2px 2px #333, 3px 3px #333, 4px 4px #333,
5px 5px #333, 6px 6px #333;
文字交错排列
文字交错排列
这里用到的和上面一样的思路,还是要把p转成span!设置letter-spacing为负数,让文字可以层叠,然后使用 定位+阴影 让前面的压在上面!
.overlap span {
letter-spacing: -20px;
/* 用阴影,后面的盖住前面的 --> 想到定位 */
text-shadow: 10px 0px 5px red;
position: relative;
}
const text = document.querySelector(".overlap");
// 不能用 outerHTML --> 有标签+class之类的东西
// 将 p 转成 span 通用函数
text.innerHTML = text.textContent
.split("")
.map((t, i, arr) => `<span style="z-index:${arr.length - i}">${t}</span>`)
.join("");
文字交融展开
文字交融展开
这里的思路也是设置letter-spacing为负数,让文字可以层叠,重点是filter: blur(10px);
和 filter: contrast(30);
文字连续光影效果
文字连续光影效果
这里也是要把p换成span,然后设置一个span的样式出来了,其他的设置延时就都可以了。
这里看着是慢慢渐变,但是对于一个span来说,其实就是由白色变成红色!
span {
font-size: 10vw;
color: #fff;
/* alternate 表示无穷动画的时候,间隔位置的动画要反向 */
animation: spread 2s var(--delay) ease-in-out infinite alternate;
}
@keyframes spread {
to {
color: red;
text-shadow: 20px 0 70px red;
}
}
文字镂空
文字镂空
这里思路其实很简单,就是把背景盖住,然后文字的背景也搞成背后的背景,然后使用background-clip: text;
并设置文字颜色为透明就行!
文字下划线动画
文字下划线动画
这里看着很简单,其实很难!必须用span这种行盒,块盒无法实现,行盒的背景才是跟随文字的!
知道了这个特性其实就不难了,剩下的就是设置背景了!
.title span {
/* 思考什么东西可以跟着行盒的方向一行行走:background */
background-image: linear-gradient(90deg, greenyellow, red);
background-repeat: no-repeat;
/* 一开始是: bottom left,但是鼠标移出是回退回去,和效果不符合!*/
background-position: bottom right;
background-size: 0px 2px;
transition: background-size 0.5s linear;
}
.title:hover span {
background-position: bottom left;
background-size: 100% 2px;
}
文字自动适配背景
文字自动适配背景
这里主要就是使用了css的滤镜 mix-blend-mode: difference;
下拉菜单过渡效果
下拉菜单过渡效果
这里的思路适用于很多,高度未知的内容显示问题!
菜鸟这里使用了4种方式,个人感觉js方式还是最好的:
const input = document.querySelector(".text");
const select = document.querySelector(".select");
input.onfocus = function () {
select.style.height = "auto";
// 获取设置自动高度后的select的高度
const selectHeight = select.offsetHeight;
// 这两句必须有,不然过渡效果有问题
select.style.height = 0;
select.offsetHeight; // --> 强制触发重排
// 将值赋值给select的style
select.style.height = selectHeight + "px";
};
input.onblur = function () {
select.style.height = 0;
};
圆形放大的hover效果
圆形放大的hover效果
这里思路是三层,图片元素作为最底层,然后before元素作为遮盖层,最后after元素设置clip-path
即可完成
.card::after {
/* 继承父元素的背景图 */
background: inherit;
clip-path: circle(0% at 50% 50%);
transition: all 0.3s;
}
/* 书写顺序不能反 见 问题img */
.card:hover::after {
clip-path: circle(50% at 50% 50%);
}
animation-delay实现动画
animation-delay(动画延时) 实现动画
这里的思路可能对一些复杂动画有帮助!
这里的思路是,将动画提前多少秒执行,那么现在就是执行多少秒时的状态!
.aniBox {
width: 50px;
height: 50px;
border-radius: 50%;
background-color: red;
/* 注意:1s、paused都必须加上;滑块得max和1s保持一致,这里多少秒那边就多大! */
/* 不带1s,那么var(--delay)就变成动画时间了 */
/* 不加paused,那么直接完成动画了,就不会停住 */
animation: move 1s var(--delay) linear forwards paused;
}
@keyframes move {
to {
transform: translateX(200px);
}
}
const range = document.querySelector(".range");
const aniBox = document.querySelector(".aniBox");
// 避免js进行复杂计算,不管实现什么延时实现动画,基本上都是这个js就行!
const calc = () => {
aniBox.style.setProperty("--delay", `-${range.value}s`);
};
range.oninput = calc;
calc();
canvas 常用方法
1、初始化
初始化canvas
const canvas = document.querySelector(".canvas");
const ctx = canvas.getContext("2d");
// 解决清晰度问题
canvas.width = window.innerWidth * devicePixelRatio;
canvas.height = window.innerHeight * devicePixelRatio;
这个是一般做法,要是想画图片或者视频,就要设置宽高为图片或者视频的宽高,eg:
2、重置坐标系
重置坐标系
canvas的坐标系,初始是容器左上角!
// 今后可以用这种方式重置坐标系!
// 对画布进行变形,让画布原点在底部中心位置
ctx.translate(canvas.width / 2, canvas.height);
// 此时的y轴指向下,反向一下
ctx.scale(1, -1);
3、遍历像素点
遍历像素点
// w --> canvas宽度 h --> canvas高度
for (let i = 0; i < w; i++) {
for (let j = 0; j < h; j++) {
// 获取index
let index = (i + w * j) * 4;
const r = data[index];
const g = data[index + 1];
const b = data[index + 2];
const a = data[index + 3];
}
}
这里的 data 由 5 获取!
4、获取点击点 index+rgba
获取点击点 index+rgba
// 点击处的 x,y 和 imgdata 的 index 的对应关系
function point2Index(x, y) {
return (x + y * canvas.width) * 4;
}
// 获取图片点击地方的rgba值
function getRgba(x, y, imgData) {
const index = point2Index(x, y);
return {
r: imgData.data[index],
g: imgData.data[index + 1],
b: imgData.data[index + 2],
a: imgData.data[index + 3],
};
}
这里的 imgData 由 5 获取!
5、获取canvas图片
获取canvas图片
// 获取imgdata --> 设置获取区域
const { width, height, data } = ctx.getImageData(
0,
0,
canvas.width,
canvas.height
);
或者
// 获取imgdata
const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
6、画 图片/视频 到canvas
画 图片/视频 到canvas
ctx.drawImage(img/video, 0, 0, canvas.width, canvas.height);
这里的 img/video,都是document对象!
7、修改canvas
修改canvas
// 简写:从index开始,替换成changeColor数组中的几个值 --> 一般四个,对应rgba
imgData.data.set(changeColor, index);
// 修改后绘制
ctx.putImageData(imgData, 0, 0);
这里的 imgData 由 5 获取!
canvas 处理图片
这里使用的就是 1、4、5、7
剩下的 canvas 我只放效果,没有效果的我就只放一个标题,具体代码去 GitHub 上学习就行!
canvas画随机树
canvas画随机树
canvas获取视频帧
canvas获取视频帧
canvas阴影画出图片
canvas阴影画出图片
这里不是canvas画出图片,而是canvas根据获取到图片的像素,然后设置一个 1px X 1px 的元素的阴影,让其显示出和图片一样的效果!
生成的html
canvas粒子时钟
canvas粒子时钟
canvas动画(点+线)
canvas动画(点+线)
动画的思路就是在一小断时间内更新坐标,清空画布重新画内容就行!
draw() {
// 添加动画
requestAnimationFrame(() => {
// 如何保证点运动 --> 点的class里面
this.draw();
});
ctx.clearRect(0, 0, canvas.width, canvas.height);
....
}
svg描边动画 (通用)
这里的思路就是设置svg的 stroke-dasharray
和 stroke-dashoffset
都为其本身长度,然后设置动画结束时 stroke-dashoffset: 0;
即可!
获取svg长度
const path = document.querySelectorAll(".p");
for (let i of path) {
// 获取 svg 的长度
const l = i.getTotalLength();
i.style.setProperty("--l", `${l}`);
}
剩下的两个菜鸟也是无法举一反三,其中还有一个压根不生效,读者可以看看能不能解决,希望解决的大佬可以留言!