
eSearch 高级图片编辑器中的 Canvas 渐变实现线性轴数学计算与径向/锥形渐变源码解析【免费下载链接】eSearch截屏 离线OCR 搜索翻译 以图搜图 贴图 录屏 万向滚动截屏 屏幕翻译 Screenshot Offline OCR Search Translate Search for picture Paste the picture on the screen Screen recorder Omnidirectional scrolling screenshot Screen translator 支持Windows Linux macOS项目地址: https://gitcode.com/GitHub_Trending/es/eSearch本篇文章以 eSearch 开发文档 docs/develop/photoEditor.md 为主体深入讲解 eSearch 高级图片编辑器中基于 HTML5 Canvas API 的渐变背景实现从 CSS 渐变与 CanvasGradient 的能力差异出发推导线性渐变轴的数学计算含保证四角全覆盖的轴长公式并对照 src/renderer/photoEditor/photoEditor.ts 源码逐行解析线性、径向、锥形三种渐变的渲染管线。读完你将掌握createLinearGradient/createRadialGradient/createConicGradient在真实项目中的调用方式、角度与坐标系的换算技巧以及渐变配置在应用内的完整数据结构。一、高级图片编辑器与渐变背景的定位eSearch 的截屏流程在 clip_window.ts 中提供高级图片编辑入口点击工具栏图标后截取到的图片会以dataURL形式通过 IPCclip_editor发送给主进程主进程在 main.ts 中createPhotoEditor()创建并最大化一个BrowserWindow加载photoEditor.html待页面加载完成后通过superPhotoEditorInit把图片回传给渲染进程随后由 photoEditor.ts 完成渲染与编辑。编辑器窗口对应 photoEditor.html的核心职责之一是在原始图片外围绘制背景。背景支持五种类型见 photoEditor.tscolor纯色image图片linear-gradient线性渐变radial-gradient径向渐变conic-gradient圆锥渐变其中后三种便是本文的主角——渐变背景。它们的 UI 控件集中在侧边栏背景分组角度number、渐变中心gx/gy0~1 相对值步长 0.01、颜色断点列表gColors见 photoEditor.ts。二、CSS 渐变与 CanvasGradient 的差异开发文档首先归纳了 CSS 渐变的四大家族线性linear、径向radial、锥形conic及其重复渐变repeating-*。但在 Canvas 侧能力是对应的却又更底层Canvas API 的渐变对象由CanvasGradient表示通过ctx.createLinearGradient()、ctx.createRadialGradient()、ctx.createConicGradient()创建与 CSS 颜色断点color stop语法不同CanvasGradient.addColorStop(offset, color)的offset 仅支持 0 到 1 之间的百分比数值不接受长度单位或deg中心位置、角度、重复等语法糖参数在 CSS 中由关键字表达在 Canvas 中则需要开发者自己计算坐标再传入 API。eSearch 的设计取舍正如文档所言我们的渐变不需要太多功能参数就只是中心位置、角度、重复和颜色断点。 对应的配置结构定义在 ShareTypes.d.tsbg.gradient.repeat: boolean; bg.gradient.repeatSize: number | ${number}px; bg.gradient.angle: number; // 角度度 bg.gradient.x: number; // 中心/起点 x0-1 相对值 bg.gradient.y: number; // 中心/起点 y0-1 相对值 bg.gradient: { offset: number; color: string }[]; // 颜色断点数组其中x、y采用相对坐标乘以画布宽高得到实际像素断点数组由若干{ offset, color }组成offset为 0~1。值得注意的实现细节bg.gradient.repeat与bg.gradient.repeatSize两个字段在类型定义中已经存在但查看 photoEditor.ts 的配置映射可以发现它们被注释掉了UI 中也没有暴露重复控件。从源码结构看重复渐变属于预留能力当前版本实际生效的是angle、x、y与颜色断点。三、线性渐变轴的数学计算文档核心CSSlinear-gradient(angle, ...)中最容易踩坑的一点渐变轴gradient line的位置决定了对角是否被裁切。默认情况下轴穿过矩形中心若轴长不足矩形边角会出现纯色溢出而非渐变过渡。文档引用 MDN 的轴示意图说明这一点并给出解法为了保证边角也应用渐变需要对轴进行计算。3.1 角度定义与数学惯例不同文档特别提醒角度angle与一般数学上的定义不同从 -y 到 x。在 CSS 约定中0deg指向正上方即 -y 方向90deg指向正右方即 x 方向顺时针旋转。换算成坐标轴方向向量即为(sin(a), -cos(a))当a 0时方向为(0, -1)向上当a 90°时方向为(1, 0)向右。这个约定在后面的公式推导中直接使用。3.2 平移轴以简化计算文档给出的关键技巧是由于是线性我们可以在轴的垂直方向平移轴以方便计算并配了平移示意图 docs/develop/assets/linear-gradient.svg平移的意图是把过中心的渐变轴等价地看作从矩形某一边出发、沿角度方向延伸的射线问题从而只需要关心轴长梯度从 0 走到 1 的线段长度坐标的精确摆放留到最后一步。这样就把二维问题降维成一维的轴长 方向问题。3.3 起始坐标与终止坐标文档直接给出了轴端点的坐标公式假设角度为锐角画布宽w、高h起始坐标(0, h)终止坐标(sin(a), h - cos(a))即从矩形左下角出发沿方向向量(sin(a), -cos(a))前进单位长度。显然这个单位长度版本只是示意——实际渲染时轴长必须按比例放大否则无法覆盖整幅画面。3.4 源码中的轴长公式对照 photoEditor.ts 的线性渐变分支实现完全继承了文档的推导if (bgType linear-gradient) { const r Math.sin(angle Math.atan(finalHeight / finalWidth)) * Math.sqrt(finalWidth ** 2 finalHeight ** 2); grd ctx.createLinearGradient( 0, finalHeight, r * Math.sin(angle), finalHeight - r * Math.cos(angle), ); }逐项解读angle (gAngle * Math.PI) / 180配置中的角度是度先转弧度Math.sqrt(finalWidth ** 2 finalHeight ** 2)矩形对角线长度d这是轴长的理论上限——沿任意方向的渐变轴只要达到对角线长度就必然能覆盖整张矩形因为矩形内任意两点距离不超过对角线Math.sin(angle Math.atan(finalHeight / finalWidth))修正系数。atan(h/w)是矩形对角线与 x 轴的夹角把渐变方向角与对角线方向角叠加后取正弦得到在矩形对角线跨度方向上当前角度渐变轴的有效投影比例。当渐变方向恰好与对角线方向一致时该系数为 1轴长取满对角线方向越偏向长边所需轴长越短。正是这个系数保证了四个边角全部落在渐变区间内既不裁切也不填充溢出终点坐标(r * sin(angle), finalHeight - r * cos(angle))与文档的(sin(a), h - cos(a))同构只是把单位长度换成了计算出的轴长r起点固定在左下角(0, finalHeight)。这里还有一个工程细节Canvas 坐标系的 y 轴向下而 CSS 角度约定0deg 向上因此终点的 y 分量写作finalHeight - r * cos(angle)向上为减与(sin(a), -cos(a))的方向向量语义完全一致。源码注释也明确标注angle 基于 y 轴。四、径向渐变与锥形渐变与线性渐变需要手算轴长不同另外两种渐变直接用中心坐标参数实现更为直白见 photoEditor.ts} else if (bgType radial-gradient) { grd ctx.createRadialGradient( x, y, 0, x, y, Math.max(finalWidth, finalHeight) / 2, ); } else { grd ctx.createConicGradient(angle, x, y); }其中x gx * finalWidth、y gy * finalHeight见 photoEditor.ts把 0~1 的相对坐标换算成像素坐标径向渐变createRadialGradient(x0, y0, r0, x1, y1, r1)的内外两个圆。源码取内圆半径 0、外圆半径max(w, h) / 2即以配置中心为圆心向四周扩散改用min(w, h)或对角线半长即可得到不同的扩散形态这正是中心位置参数的意义所在锥形渐变createConicGradient(startAngle, x, y)以(x, y)为旋转中心从startAngle弧度处开始按顺时针扫过一圈。源码直接复用angle已转弧度作为起始角。两种渐变与线性渐变共用同一份颜色断点数组gradient最后统一通过grd.addColorStop(item.offset, item.color)循环写入见 photoEditor.ts外层再用ctx.fillRect(0, 0, finalWidth, finalHeight)填充整幅背景画布。颜色断点的 UI 与默认值断点编辑器gColors()见 photoEditor.ts为每个断点提供两列输入颜色值文本输入框与 offsetnumber 输入框min0, max1, step0.01并支持新增默认新增一个#0000透明黑、offset 0.5 的断点与-删除。断点输入即时派发input事件触发重绘实现所见即所得。这与文档颜色断点仅支持百分比的说明一一对应Canvas 的 offset 本质就是 0~1 的百分比。五、配置结构、默认值与管理渐变参数不是孤立存在的它们属于高级图片编辑的整份样式配置。defaultConfig见 photoEditor.ts给出了所有字段的默认值{ name: 0, raduis: 0, // 圆角 outerRadius: false, // 外圆角 bgType: color, // 背景类型 bgColor: , // 纯色背景 bgUrl: , // 图片背景 bg.gradient.angle: 0, bg.gradient.repeat: false, bg.gradient.repeatSize: 0, bg.gradient.x: 0, bg.gradient.y: 0, bg.gradient: [], // 颜色断点 shadow.x: 0, shadow.y: 0, shadow.blur: 0, shadow.color: , padding.x: 0, padding.y: 0, autoPadding: false, }多套配置通过高级图片编辑.配置数组与高级图片编辑.默认配置当前选中项的name持久化在应用 store 中主进程侧默认值见 main.ts侧边栏顶部的配置下拉pzSelect()见 photoEditor.ts支持切换、新增复制当前样式并生成随机后缀名、删除配置getStyleData()会把缺省的字段用默认值补齐保证旧配置向后兼容见 photoEditor.tsconfigMap见 photoEditor.ts把每个 UI 控件映射到样式字段并指定parse函数——例如angle、raduis、gx、gy、阴影、边距等数值字段统一Number()解析颜色字段直接存字符串。每次控件input都会更新styleData并触发updatePreview()重绘。六、完整的渲染管线渐变如何与圆角、阴影、边距协同updatePreview()见 photoEditor.ts是理解渐变落地全貌的关键。整幅输出画布尺寸为finalWidth photoWidth 2 * padX finalHeight photoHeight 2 * padY即原始图片四周按padding.x / padding.y留出边距边距区域就是背景渐变的绘制区域。渲染顺序为外圆角裁切若开启outerRadius先ctx.roundRect(...)clip()对整幅输出画布做圆角裁剪外圆角半径 内圆角 最小边距绘制背景按bgType走纯色 / 图片 / 渐变三个分支渐变即本文第三节、第四节的逻辑fillRect填满整幅画布——对渐变而言这恰好把第一节计算的轴完整覆盖到边距区域绘制照片setPhoto()见 photoEditor.ts把照片以createPattern图案填充方式绘制到(padX, padY)位置并施加shadowOffsetX / shadowOffsetY / shadowBlur / shadowColor阴影参数照片本身用roundRect圆角裁剪配合canvas.style.borderRadius让预览与外圆角一致。至此渐变背景、照片圆角、投影阴影、四周边距被完整合成到一张画布上。用户在侧边栏导出分组还可以选择 PNG / JPEG / WebP / BMP 格式与质量0~1并按 1、3/4、1/2、1/3、1/4、1/5 或自动宽/高缩放后导出或复制见 photoEditor.ts 与getImg()photoEditor.ts。七、扩展阅读渐变之外的编辑器能力虽然本文聚焦渐变但高级图片编辑器还内置了魔法橡皮Magic Pen见 photoEditor.ts用户涂抹出 mask 后程序通过onnxruntime-node加载userData/models/inpaint/migan_pipeline_v2.onnx模型把原图与 mask 组装为[1,3,h,w]/[1,1,h,w]的张量输入推理再将输出重组为ImageData回填到画布推理细节见 removeObj.ts。模型需在设置的人工智能页面下载见 setting.ts运行后端由AI.运行后端配置决定cpu / cuda / coreml / directml / webgpu 之一。理解这条管线有助于把背景渐变与内容修复两条编辑链路串起来看待。总结eSearch 高级图片编辑器用最精简的参数面角度、中心位置、颜色断点覆盖了三种 Canvas 渐变其中线性渐变的轴计算是全篇的数学核心角度遵循从 -y 到 x的 CSS 约定起点固定在(0, h)轴长由sin(angle atan(h/w)) * sqrt(w²h²)决定从而保证四个边角都被渐变覆盖而不出现裁切。径向与锥形渐变则把工作交给createRadialGradient/createConicGradient的内置圆心参数。开发者若要在自己的 Canvas 项目中复现同等效果直接对照 photoEditor.ts 的三个分支即可——公式、坐标换算与断点填充逻辑都是自包含的。【免费下载链接】eSearch截屏 离线OCR 搜索翻译 以图搜图 贴图 录屏 万向滚动截屏 屏幕翻译 Screenshot Offline OCR Search Translate Search for picture Paste the picture on the screen Screen recorder Omnidirectional scrolling screenshot Screen translator 支持Windows Linux macOS项目地址: https://gitcode.com/GitHub_Trending/es/eSearch创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考