*
以硬件加速的WebGL性能创建出惊人,动画的3D梯度.
✨ 尝试交互式编辑器 ✨
用我们的视觉编辑器设计完美的梯度, 以20+预设和实时预览为特色. 导出配置并立即在您的工程中使用 .

* 安装
npm install @firecms/neat
或者说
yarn add @firecms/neat
QQ 快速启动
基本用途
import { NeatGradient } from "@firecms/neat";
const gradient = new NeatGradient({
ref: document.getElementById("canvas"),
colors: [
{ color: "#FF5772", enabled: true },
{ color: "#4CB4BB", enabled: true },
{ color: "#FFC600", enabled: true },
{ color: "#8B6AE6", enabled: true },
{ color: "#2E0EC7", enabled: true }
],
speed: 4,
waveAmplitude: 5,
backgroundColor: "#003FFF",
backgroundAlpha: 1
});
// Clean up when done (important for React, Vue, etc.)
gradient.destroy();
反应示例
import { useEffect, useRef } from "react";
import { NeatGradient, NeatConfig } from "@firecms/neat";
function BackgroundGradient() {
const canvasRef = useRef<HTMLCanvasElement>(null);
const gradientRef = useRef<NeatGradient | null>(null);
useEffect(() => {
if (!canvasRef.current) return;
gradientRef.current = new NeatGradient({
ref: canvasRef.current,
colors: [
{ color: "#FF5772", enabled: true },
{ color: "#4CB4BB", enabled: true },
{ color: "#FFC600", enabled: true }
],
speed: 3,
waveAmplitude: 5
});
return () => gradientRef.current?.destroy();
}, []);
return (
<canvas
ref={canvasRef}
style={{
position: "fixed",
top: 0,
left: 0,
width: "100%",
height: "100%",
zIndex: -1
}}
/>
);
}
配置 API
核心动画
| 财产 | 类型 | 默认 | 范围 | 说明 |
|---|---|---|---|---|
speed | number | 4 | 0-10 | 动画速度 (0 = 静态) |
waveAmplitude | number | 3 | 0-10 | 波高强度 |
waveFrequencyX | number | 5 | 0-10 | 水平波频率 |
waveFrequencyY | number | 5 | 0-10 | 垂直波频率 |
颜色
| 财产 | 类型 | 默认 | 说明 |
|---|---|---|---|
colors | NeatColor[] | 需求 | 颜色对象阵列( 最多为 6) |
colorBlending | number | 5 | 颜色如何混合( 0- 10) |
colorBrightness | number | 1 | 总体亮度乘数 |
colorSaturation | number | 0 | 颜色饱和度调整( 10- 10) |
horizontalPressure | number | 3 | 水平颜色分布( 0- 10) |
verticalPressure | number | 3 | 垂直颜色分布( 0- 10) |
颜色对象 :
{
color: string; // Hex color (e.g., "#FF5772")
enabled: boolean; // Toggle color on/off
influence?: number; // Color strength (0-1, optional)
}
视觉效果
| 财产 | 类型 | 默认 | 说明 |
|---|---|---|---|
shadows | number | 4 | 阴影强度 (0-10) |
highlights | number | 4 | 突出显示强度( 0- 10) |
grainIntensity | number | 0.55 | 胶片谷物数量(0-1) |
grainScale | number | 2 | 谷物大小 |
grainSparsity | number | 0.0 | 谷物分配螺旋性 (0-1) |
grainSpeed | number | 0.1 | 谷物动画速度 |
wireframe | boolean | false | 显示线框网格 |
高级阴影处理后处理( P)
域旋转
| 财产 | 类型 | 默认 | 说明 |
|---|---|---|---|
domainWarpEnabled | boolean | false | 启用域扭曲 |
domainWarpIntensity | number | 0.5 | 域名拼接的强度 |
domainWarpScale | number | 1.0 | 旋转的空间频率尺度 |
维尼特
| 财产 | 类型 | 默认 | 说明 |
|---|---|---|---|
vignetteIntensity | number | 0.0 | 角落的黑暗强度( 0-1) |
vignetteRadius | number | 0.8 | 放射坠落起始距离 |
弗雷斯内尔( Rim Glow)
| 财产 | 类型 | 默认 | 说明 |
|---|---|---|---|
fresnelEnabled | boolean | false | 启用外缘阴影效果 |
fresnelPower | number | 2.0 | 轮回的光芒 |
fresnelIntensity | number | 0.5 | 发光效果的亮度 |
fresnelColor | string | "#FFFFFF" | 环形发光的颜色( hex) |
迷恋
| 财产 | 类型 | 默认 | 说明 |
|---|---|---|---|
iridescenceEnabled | boolean | false | 启用肥皂泡样式颜色转换 |
iridescenceIntensity | number | 0.5 | 颜色转变效应的强度 |
iridescenceSpeed | number | 1.0 | 颜色循环速度 |
布鲁姆( 假花花)
| 财产 | 类型 | 默认 | 说明 |
|---|---|---|---|
bloomIntensity | number | 0.0 | 从亮点出血的发光强度 |
bloomThreshold | number | 0.7 | 开花候选像素的亮度阈值 |
染色异常
| 财产 | 类型 | 默认 | 说明 |
|---|---|---|---|
chromaticAberration | number | 0.0 | 镜头彩色通道分割距离 |
3D 地美图和形状
| 财产 | 类型 | 默认 | 说明 |
|---|---|---|---|
shapeType | 'plane' | 'sphere' | 'torus' | 'cylinder' | 'ribbon' | 'plane' | 3D 形状几何使梯度在 |
shapeRotationX | number | 0 | 手动 X 旋转(弧度) |
shapeRotationY | number | 0 | 手动 Y 旋转( 弧度) |
shapeRotationZ | number | 0 | 手动 Z 旋转(弧度) |
shapeAutoRotateSpeedX | number | 0 | X 轴上的自动旋转速度 |
shapeAutoRotateSpeedY | number | 0 | Y 轴上的自动旋转速度 |
sphereRadius | number | 15 | 球体形状的半径 |
torusRadius | number | 15 | 托鲁斯主环半径 |
torusTube | number | 5 | Torus 内管厚度 |
cylinderRadius | number | 10 | 圆柱形半径 |
cylinderHeight | number | 40 | 圆柱形状的高度 |
planeBend | number | 0 | 应用在平面几何上的 Bding 扭曲 |
planeTwist | number | 0 | 对平面几何应用的扭曲 |
silhouetteFade | number | 0.25 | 球体/托盘的边缘透明度逐渐消失 |
cylinderFade | number | 0.08 | 向气瓶末端的透明化 |
ribbonFade | number | 0.05 | 透明度向着丝带的尽头消失 |
flatShading | boolean | true | 对几何常态使用平面阴影 |
相机设置
| 财产 | 类型 | 默认 | 说明 |
|---|---|---|---|
cameraLock | boolean | false | 锁定相机控制并阻止拖动旋转 |
cameraX | number | 0 | 相机沿 X 轴进行偏移 |
cameraY | number | 0 | Y轴相机偏移 |
cameraZ | number | 0 | 相机沿 Z 轴偏移 |
cameraRotationX | number | 0 | 相机弹出旋转(弧度) |
cameraRotationY | number | 0 | 相机 yaw 旋转(弧度) |
cameraRotationZ | number | 0 | 相机滚动旋转(弧度) |
cameraZoom | number | 1.0 | 相机缩放因子 |
背景情况
| 财产 | 类型 | 默认 | 说明 |
|---|---|---|---|
backgroundColor | string | "#FFFFFF" | 背景颜色 (hex) |
backgroundAlpha | number | 1 | 背景不透明(0-1) |
业绩
| 财产 | 类型 | 默认 | 说明 |
|---|---|---|---|
resolution | number | 1 | 网格密度(0.1-2,较低=业绩更好) |
renderScale | number | 1 | 相对于画布的 CSS 大小( 0.1-3) 绘制缓冲大小 |
resolution 是网格密度,而不是像素分辨率. 它缩小了流离失所的规模
网格 - 平面的240x240段 1,120x120 用于3D形状. 大多数
每帧成本在顶点阴影中,所以这是第一个拒绝.
网格也上限为每6个帆布像素大约一个段,所以很小
帆布从不支付它不能显示的细节.
renderScale 是像素的一个. 时 0.75 梯度使像素减少44%
和浏览器对结果进行分级——通常在内容后面看不见
在低端设备上最便宜的赢家. 它需要CSS的画布大小;如果
布局大小来自宽度/高度属性,缩放被忽略(带有
因此元素不能在每次调整大小时缩小.
speed: 0 毫无代价. 时钟停了 每一帧都是一样的,
因此,渲染环形公园本身, 只有在你改变一个属性时才醒来。 一个静态
梯度是一次性的渲染,而不是60英尺重绘相同的图像.
滚动集成
| 财产 | 类型 | 默认 | 说明 |
|---|---|---|---|
yOffset | number | 0 | 垂直滚动偏移 |
yOffsetWaveMultiplier | number | 4 | 卷轴对波浪的影响有多大(0-20) |
yOffsetColorMultiplier | number | 4 | 卷轴影响颜色多少( 0-20) |
yOffsetFlowMultiplier | number | 4 | 卷轴影响流量字段多少( 0-20) |
流场( 扭曲)
| 财产 | 类型 | 默认 | 说明 |
|---|---|---|---|
flowEnabled | boolean | true | 启用流量字段扭曲 |
flowDistortionA | number | 0 | 主扭曲振幅 |
flowDistortionB | number | 0 | 二次扭曲频率 |
flowScale | number | 1 | 外地总流量规模 |
flowEase | number | 0 | 流场平滑 (0-1) |
程序性纹理重叠
| 财产 | 类型 | 默认 | 说明 |
|---|---|---|---|
enableProceduralTexture | boolean | false | 启用纹理覆盖 |
textureMode | 'bitmap' | 'baked' | 'bitmap' | 纹理如何绘制——见下文 |
textureBakeResolution | number | 0 | 烧焦纹理大小; 0 从画布取出 |
bakeEdgeSoftness | number | 1 | 烘焙时反变相宽度, 单位为输出特克塞尔 |
textureVoidLikelihood | number | 0.45 | 纹理相隔频率 (0-1) |
textureVoidWidthMin | number | 200 | 最小空隙宽度 |
textureVoidWidthMax | number | 486 | 最大间隙宽度 |
textureBandDensity | number | 2.15 | 纹理带密度 |
textureColorBlending | number | 0.01 | 纹理中的颜色混合 (0-1) |
textureSeed | number | 333 | 纹理随机种子 |
textureEase | number | 0.5 | 流量/图像混合 (0=流量, 1=图像) |
transparentTextureVoid | boolean | false | 显示为透明而非使用程序背景颜色 |
proceduralBackgroundColor | string | "#000000" | 纹理空白颜色 |
textureShapeTriangles | number | 20 | 三角形状数 |
textureShapeCircles | number | 15 | 圆形数 |
textureShapeBars | number | 15 | 条形状数 |
textureShapeSquiggles | number | 10 | 螺旋形状数量 |
位图对已烤
textureMode 决定上面的形状如何被引入纹理中。 两者
模式读取相同的生成的相片, 所以给定 textureSeed 生产
无论哪种方式, 和相同的组成, 和两者最终作为一个普通的 迷雾纹理——
运行时间成本相同。 不同的是纹理有多尖.
bitmap (默认)以1024px的硬码通过Canvas2D来绘制形状.
边缘落在网格上 一旦相机放大了纹理 它们就会软化
和对角显示 楼梯步入 他们的网格上.
baked 对 GPU 进行光栅化分析:精确的每像素
边缘覆盖,以来自画布而不是固定的分辨率表示。 没错
两者生成的速度也越快
全屏英雄的 Canvas2D 路径,因为它跳过 CPU 绘图和
上传.
bitmap | baked | |
|---|---|---|
| 决议 | 1024,总是 | 从帆布, 1024–2048 (4096 选入) |
| 边缘质量 | Canvas2D 防伪 | 精确分析覆盖率 |
| 生成 | ~35分钟 | ~20 ms 时 |
| 运行时间 | 一个纹理获取 | 一个纹理获取 |
| 内存 | ~5.5 MB 键 | ~22 MB 于 2048 时 |
须知三限:
- 烘焙时不支持抽屉 并被弃去警告. Cubic Béziers 没有封闭式的相距功能,所以成本很高 大约是其他形状的十倍.
baked需要网络GL2 (单位:千美元)texelFetch和浮起的纹理bitmap否则。 读取activeTextureMode用于实际使用的模式.- 记忆是每个实例. WebGL 纹理无法在上下文之间共享,
和每个
NeatGradient拥有自己的画布和上下文,所以有一个页面带有 他们中有几个人每人付费。 这就是为什么2048年的默认上限 4096岁以上textureBakeResolution故意的 故意的.
const gradient = new NeatGradient({
ref: canvas,
enableProceduralTexture: true,
textureMode: "baked",
textureShapeSquiggles: 0, // not available when baking
textureBakeResolution: 0, // 0 = derive from the canvas
bakeEdgeSoftness: 1.0, // antialiasing width, in output texels
// ...
});
gradient.activeTextureMode; // 'baked', or 'bitmap' if it had to fall back
gradient.textureMode = "bitmap"; // switchable at runtime
API 方法
destroy()
清理 WebGL 上下文,事件收听器,并删除任何被注入的 DOM 元素. 当组件卸载防止内存出漏时调用此功能( React, Vue等必需).
gradient.destroy();
QQ 动态属性更新
所有属性都可以实时更新 :
// Animation
gradient.speed = 6;
gradient.waveAmplitude = 8;
// Colors
gradient.colors = [
{ color: "#FF0000", enabled: true },
{ color: "#00FF00", enabled: true }
];
// 3D Shape Geometries & Auto-Rotation
gradient.shapeType = "sphere";
gradient.shapeAutoRotateSpeedY = 1.5;
// Advanced Post-Processing Effects
gradient.iridescenceEnabled = true;
gradient.fresnelEnabled = true;
gradient.fresnelColor = "#FF0055";
// Effects
gradient.grainIntensity = 0.5;
// Texture
gradient.enableProceduralTexture = true;
gradient.textureEase = 0.7;
一个梯度,许多画布
浏览器只授予少数活的 WebGL 语境, 以及每个额外的 NeatGradient
运行自己的阴影。 所以不要每张牌创造一张 —— 创建 一个 渐变和镜像
随你喜欢的平地2D画布 每个镜子可以显示不同的收成,
他们都保持完美的同步,每个镜像的成本是GPU副本而不是一个
第二次妥协.
就是这样 编辑器 将梯度预览为 a 网站英雄,手机屏幕和一行相声同时出现.
源梯度需要 preserveDrawingBuffer: true 没有它,绘图缓冲
在堆肥后清除, 并且没有可用的副本 :
import { NeatGradient } from "@firecms/neat";
const source = document.getElementById("source") as HTMLCanvasElement;
const gradient = new NeatGradient({
ref: source,
preserveDrawingBuffer: true, // required to read the canvas from outside its own frame
colors: [
{ color: "#FF5772", enabled: true },
{ color: "#4CB4BB", enabled: true },
{ color: "#FFC600", enabled: true }
]
});
然后在任何你想去的地方 照照它的区域:
type MirrorOptions = {
cx?: number; // horizontal centre of the crop, 0–1
cy?: number; // vertical centre of the crop, 0–1
zoom?: number; // 1 shows as much as fits, 2 shows half
fps?: number; // refresh rate — drop it for small decorative mirrors
};
function mirror(target: HTMLCanvasElement, options: MirrorOptions = {}) {
const { cx = 0.5, cy = 0.5, zoom = 1, fps = 60 } = options;
const ctx = target.getContext("2d");
const interval = 1000 / fps;
let raf = 0;
let last = 0;
const draw = (now: number) => {
raf = requestAnimationFrame(draw);
if (!ctx || now - last < interval) return;
last = now;
const dpr = Math.min(window.devicePixelRatio || 1, 2);
const w = Math.round(target.clientWidth * dpr);
const h = Math.round(target.clientHeight * dpr);
if (!w || !h || !source.width || !source.height) return;
if (target.width !== w || target.height !== h) {
target.width = w;
target.height = h;
}
// Largest crop of the source matching the target's aspect ratio, then zoomed
const aspect = w / h;
let cropW = source.width;
let cropH = source.width / aspect;
if (cropH > source.height) {
cropH = source.height;
cropW = source.height * aspect;
}
cropW /= zoom;
cropH /= zoom;
const sx = Math.min(Math.max(cx * source.width - cropW / 2, 0), source.width - cropW);
const sy = Math.min(Math.max(cy * source.height - cropH / 2, 0), source.height - cropH);
ctx.clearRect(0, 0, w, h);
ctx.drawImage(source, sx, sy, cropW, cropH, 0, 0, w, h);
};
raf = requestAnimationFrame(draw);
return () => cancelAnimationFrame(raf);
}
// A hero, a tight crop for a card, and a slow-refreshing avatar
mirror(document.getElementById("hero") as HTMLCanvasElement);
mirror(document.getElementById("card") as HTMLCanvasElement, { cx: 0.3, cy: 0.4, zoom: 1.7 });
mirror(document.getElementById("avatar") as HTMLCanvasElement, { cx: 0.7, cy: 0.6, zoom: 10, fps: 10 });
值得我们知道的事
- 源头帆布必须保持布局.
display: none折叠到零大小 渐变停止渲染——用position: fixed; inset: 0; z-index: -1或者用不透明的层层遮住. - 使用一个
requestAnimationFrame环绕所有镜像而非每个镜像;示例 上面是模糊的,但有一个共享的勾动器,可以更好地显示列表的比分. drawImage从 WebGL 画布上看到一个跨文本副本——在桌面上很便宜,很显著 在电话。 在那里,将设备像素比上限为1,运行镜像比为30英尺,并给出 小的装饰花花(avatar,图标) 10 fps. 没人知道40px圈.- 镜子是普通的画布,所以它们取
border-radius, (中文(简体) ),mask-image, (中文(简体) ),filter还有CSS提供的其他东西 小小的镜子模糊到无所事事 使环境变得很好 在布局后面发光. - 只有源头需要
preserveDrawingBuffer。这也是什么使downloadAsPNG()和视频拍摄工作.
QQ 类型脚本支持
完整类型脚本定义包括:
import { NeatGradient, NeatConfig, NeatColor, NeatController } from "@firecms/neat";
const config: NeatConfig = {
// ... fully typed config
};
const gradient: NeatController = new NeatGradient(config);
许可证
Neat 将在 麻省理工学院许可证+共同条款。 。 。 .
你可以这样:
- * 个人项目自由使用
- 在商业项目中自由使用(例如SaaS登陆页,公司网站)
- 修改和再分配(带有归属)
- 用于开源项目
你不能说:
- 卖出软件
- 将它包含在您出售的付费模板或主题构建器中
- 提供软件作为有偿服务
删除 NEAT 水印
为 12欧元一次性 (每个域名)去除NEAT水印和控制台品牌.
然后通过您配置中的密钥 :
const gradient = new NeatGradient({
ref: canvas,
colors: [...],
licenseKey: "NEAT-eyJ0eXBlI..." // Your license key
});
每个密钥被锁入您在退出时指定的域( 包含子域) 。 联合国 localhost 总是没有钥匙的.
同样的密钥从 PNG 和视频输出中移除了水印 编辑器: 单击 支持,则 激活您的密钥把它粘起来.
• 信贷
创建于 重新基地 与
问题和贡献
找到错误还是有特性请求 ?
链接
由基地团队制作