前篇传送门:https://juejin.im/post/6844904033405108232
其实大多数的技巧前篇都已经讲完了,本文算是具有补充性质的番外篇吧0.0
如何在 CSS 中创建立体的方块呢?用以下的 SCSS mixin 即可
方块的长度、高度、深度都可以通过 CSS 变量自由调节
@mixin cube($width, $height, $depth) {
&__front {
@include cube-front($width, $height, $depth);
}
&__back {
@include cube-back($width, $height, $depth);
}
&__right {
@include cube-right($width, $height, $depth);
}
&__left {
@include cube-left($width, $height, $depth);
}
&__top {
@include cube-top($width, $height, $depth);
}
&__bottom {
@include cube-bottom($width, $height, $depth);
}
.face {
position: absolute;
}
}
@mixin cube-front($width, $height, $depth) {
width: var($width);
height: var($height);
transform-origin: bottom left;
transform: rotateX(-90deg) translateZ(calc(calc(var(#{$depth}) * 2) - var(#{$height})));
}
@mixin cube-back($width, $height, $depth) {
width: var($width);
height: var($height);
transform-origin: top left;
transform: rotateX(-90deg) rotateY(180deg) translateX(calc(var(#{$width}) * -1)) translateY(
calc(var(#{$height}) * -1)
);
}
@mixin cube-right($width, $height, $depth) {
width: calc(var(#{$depth}) * 2);
height: var($height);
transform-origin: top left;
transform: rotateY(90deg) rotateZ(-90deg) translateZ(var(#{$width})) translateX(calc(var(#{$depth}) * -2)) translateY(calc(var(
#{$height}
) * -1));
}
@mixin cube-left($width, $height, $depth) {
width: calc(var(#{$depth}) * 2);
height: var($height);
transform-origin: top left;
transform: rotateY(-90deg) rotateZ(90deg) translateY(calc(var(#{$height}) * -1));
}
@mixin cube-top($width, $height, $depth) {
width: var($width);
height: calc(var(#{$depth}) * 2);
transform-origin: top left;
transform: translateZ(var($height));
}
@mixin cube-bottom($width, $height, $depth) {
width: var($width);
height: calc(var(#{$depth}) * 2);
transform-origin: top left;
transform: rotateY(180deg) translateX(calc(var(#{$width}) * -1));
}
.cube {
--cube-width: 3rem;
--cube-height: 3rem;
--cube-depth: 1.5rem;
@include cube(--cube-width, --cube-height, --cube-depth);
width: 3rem;
height: 3rem;
}
给多个方块应用交错动画会产生如下效果
.spiral-tower {
display: grid;
grid-auto-flow: row;
transform: rotateX(-30deg) rotateY(45deg);
.cube {
@for $i from 1 through 48 {
&:nth-child(#{$i}) {
animation-delay: 0.015s * ($i - 1);
}
}
}
}
@keyframes spin {
0%,
15% {
transform: rotateY(0);
}
85%,
100% {
transform: rotateY(1turn);
}
}
本 demo 地址:Spiral Tower
在 CSS 动画中,我们无法直接使变量动起来(其实能动,但很生硬)
这时我们就得求助于 CSS Houdini,将变量声明为长度单位类型即可,因为长度单位是可以动起来的
CSS.registerProperty({
name: "--cube-width",
syntax: "<length>",
initialValue: 0,
inherits: true,
});
CSS.registerProperty({
name: "--cube-height",
syntax: "<length>",
initialValue: 0,
inherits: true,
});
CSS.registerProperty({
name: "--cube-depth",
syntax: "<length>",
initialValue: 0,
inherits: true,
});
本 demo 地址:3D Stair Loading
在上一篇我们提到了如何用 JS 来分割文本,本篇将介绍一种更简洁的实现方法——gsap 的 SplitText 插件,利用它我们能用更少的代码来实现下图的效果
<div class="staggered-land-in font-bold text-2xl">Fushigi no Monogatari</div>
const t1 = gsap.timeline();
const staggeredLandInText = new SplitText(".staggered-land-in", {
type: "chars",
});
t1.from(staggeredLandInText.chars, {
duration: 0.8,
opacity: 0,
y: "-20%",
stagger: 0.05,
});
简化版 demo 地址:SplitText Starterhttps://codepen.io/alphardex/pen/ZEWRBJp)
简单的动画固然可以实现,那么相对复杂一点的动画呢?这时候还是要依靠强大的@keyframes 和 CSS 变量
注:尽管 gsap 目前也支持 keyframes,但是无法和交错动画结合起来,因此用@keyframes 作为替代方案
<div class="staggered-scale-in font-bold text-6xl">Never Never Give Up</div>
.scale-in-bounce {
animation: scale-in-bounce 0.4s both;
animation-delay: calc(0.1s * var(--i));
}
@keyframes scale-in-bounce {
0% {
opacity: 0;
transform: scale(2);
}
40% {
opacity: 1;
transform: scale(0.8);
}
100% {
opacity: 1;
transform: scale(1);
}
}
const t1 = gsap.timeline();
const staggeredScaleInText = new SplitText(".staggered-scale-in", {
type: "chars",
});
const staggeredScaleInChars = staggeredScaleInText.chars;
staggeredScaleInChars.forEach((item, i) => {
item.style.setProperty("--i", `${i}`);
});
t1.to(staggeredScaleInChars, {
className: "scale-in-bounce",
});
本 demo 地址:Staggered Scale In Text
CSS 的滤镜其实都是 SVG 滤镜的封装版本,方便我们使用而已
SVG 滤镜则更加灵活强大,以下是几个常见的滤镜使用场景
附在线调试 SVG 滤镜的网站:SVG Filters
<svg width="0" height="0" class="absolute">
<filter id="goo">
<feGaussianBlur stdDeviation="10 10" in="SourceGraphic" result="blur" />
<feColorMatrix
type="matrix"
values="1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 18 -7"
in="blur"
result="colormatrix"
/>
<feComposite in="SourceGraphic" in2="colormatrix" operator="over" result="composite" />
</filter>
</svg>
.gooey {
filter: url("#goo");
}
本 demo 地址:SVG Filter Gooey Menu
<svg width="0" height="0" class="absolute">
<filter id="glitch">
<feTurbulence type="fractalNoise" baseFrequency="0.00001 0.000001" numOctaves="1" result="turbulence1">
<animate
attributeName="baseFrequency"
from="0.00001 0.000001"
to="0.00001 0.4"
dur="0.4s"
id="glitch1"
fill="freeze"
repeatCount="indefinite"
></animate>
<animate
attributeName="baseFrequency"
from="0.00001 0.4"
to="0.00001 0.2"
dur="0.2s"
begin="glitch1.end"
fill="freeze"
repeatCount="indefinite"
></animate>
</feTurbulence>
<feDisplacementMap
in="SourceGraphic"
in2="turbulence1"
scale="30"
xChannelSelector="R"
yChannelSelector="G"
result="displacementMap"
/>
</filter>
</svg>
.glitch {
filter: url("#glitch");
}
本 demo 地址:SVG Filter Glitch Button
CSS 滤镜的 blur 是全方位模糊,而 SVG 滤镜的 blur 可以控制单方向的模糊
<svg width="0" height="0" class="absolute">
<filter id="motion-blur" filterUnits="userSpaceOnUse">
<feGaussianBlur stdDeviation="100 0" in="SourceGraphic" result="blur">
<animate dur="0.6s" attributeName="stdDeviation" from="100 0" to="0 0" fill="freeze"></animate>
</feGaussianBlur>
</filter>
</svg>
.motion-blur {
filter: url("#motion-blur");
}
本 demo 地址:SVG Filter Motion Blur
有时候我们想做出一种过渡式的半透明效果,类似下图这样的
这时候就得借助 mask 属性了,因为图片与 mask 生成的渐变的 transparent 的重叠部分会变透明
.divider-grad-mask {
background: linear-gradient(90deg, var(--blue-color) 0 50%, transparent 0 100%) 0 0 / 2rem 1rem;
mask: linear-gradient(-90deg, black, transparent);
}
demo 地址:Gradient Mask Divider
和 clip-path 结合也会相当有意思,如下图所示的加载特效
demo 地址:Mask Loader
上篇提到了利用 Web Animations API 实现鼠标悬浮跟踪的效果,但其实 CSS 变量也能实现,而且更加简洁高效
在 CSS 中定义 x 和 y 变量,然后在 JS 中监听鼠标移动事件并获取鼠标坐标,更新对应的 x 和 y 变量即可
:root {
--mouse-x: 0;
--mouse-y: 0;
}
.target {
transform: translate(var(--mouse-x), var(--mouse-y));
}
let mouseX = 0;
let mouseY = 0;
let x = 0;
let y = 0;
let offset = 50; // center
let windowWidth = window.innerWidth;
let windowHeight = window.innerHeight;
const percentage = (value, total) => (value / total) * 100;
window.addEventListener("mousemove", (e) => {
mouseX = e.clientX;
mouseY = e.clientY;
x = percentage(mouseX, windowWidth) - offset;
y = percentage(mouseY, windowHeight) - offset;
document.documentElement.style.setProperty("--mouse-x", `${x}%`);
document.documentElement.style.setProperty("--mouse-y", `${y}%`);
});
window.addEventListener("resize", () => {
windowWidth = window.innerWidth;
windowHeight = window.innerHeight;
});
img简化版地址:Mousemove Starter
如果将鼠标跟踪和交错动画结合起来,再加点模糊滤镜,就能创作出帅气的残影效果
本 demo 地址:Motion Table - Delay
为了做出一个图片碎片运动相关的动画,或者是一个拼图游戏,我们就要对一张图片进行分割,且块数、大小等都能随意控制,这时CSS变量就能发挥它的用场了
.puzzle {
--puzzle-width: 16rem;
--puzzle-height: 24rem;
--puzzle-row: 3;
--puzzle-col: 4;
--puzzle-gap: 1px;
--puzzle-frag-width: calc(var(--puzzle-width) / var(--puzzle-col));
--puzzle-frag-height: calc(var(--puzzle-height) / var(--puzzle-row));
--puzzle-img: url(...);
display: flex;
flex-wrap: wrap;
width: calc(var(--puzzle-width) + calc(var(--puzzle-col) * var(--puzzle-gap) * 2));
height: calc(var(--puzzle-height) + calc(var(--puzzle-row) * var(--puzzle-gap) * 2));
.fragment {
--x-offset: calc(var(--x) * var(--puzzle-frag-width) * -1);
--y-offset: calc(var(--y) * var(--puzzle-frag-height) * -1);
width: var(--puzzle-frag-width);
height: var(--puzzle-frag-height);
margin: var(--puzzle-gap);
background: var(--puzzle-img) var(--x-offset) var(--y-offset) / var(--puzzle-width) var(--puzzle-height) no-repeat;
}
}
在JS中,设定好变量值并动态生成切片的xy坐标,即可完成图片的分割
class Puzzle {
constructor(el, width = 16, height = 24, row = 3, col = 3, gap = 1) {
this.el = el;
this.fragments = el.children;
this.width = width;
this.height = height;
this.row = row;
this.col = col;
this.gap = gap;
}
create() {
this.ids = [...Array(this.row * this.col).keys()];
const puzzle = this.el;
const fragments = this.fragments;
if (fragments.length) {
Array.from(fragments).forEach((item) => item.remove());
}
puzzle.style.setProperty("--puzzle-width", this.width + "rem");
puzzle.style.setProperty("--puzzle-height", this.height + "rem");
puzzle.style.setProperty("--puzzle-row", this.row);
puzzle.style.setProperty("--puzzle-col", this.col);
puzzle.style.setProperty("--puzzle-gap", this.gap + "px");
for (let i = 0; i < this.row; i++) {
for (let j = 0; j < this.col; j++) {
const fragment = document.createElement("div");
fragment.className = "fragment";
fragment.style.setProperty("--x", j);
fragment.style.setProperty("--y", i);
fragment.style.setProperty("--i", j + i * this.col);
puzzle.appendChild(fragment);
}
}
}
}
const puzzle = new Puzzle(document.querySelector(".puzzle"));
本demo地址:Split Image With CSS Variable
本demo地址:Elastic Love
本demo地址:Infinite Line Animation
本demo地址:Orbit Reverse
本demo地址:Motion Table - Solid Rotation
本demo地址:Motion Table - Symmetric Move
以上几个复杂的动画或多或少都有以下的特征:
div
很多,对布局的要求很高@keyframes
很多,对动画的要求很高案例5的教程已经写在之前的博文“画物语——CSS动画之美”里了,其余案例亦可以用此文提到的方法进行研究
笔者的CSS动画作品全放在这个集合里了:CSS Animation Collection
螺旋阶梯动画(灵感来自灰色的果实OP)
本demo地址:Spiral Stair Loading
❝外链演示效果,请点击阅读原文查看
❞
本文由哈喽比特于4年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/kHBBxXap6dKIZojeYnjGPA
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。