使用 Alpha 通道绘制重叠的圆圈

2024-01-16

这个问题已经在这里得到了回答:重叠圆的组合面积 https://stackoverflow.com/questions/1667310/combined-area-of-overlapping-circles

不过我的问题更具体。我在其他任意大小的圆圈内有任意数量的任意大小的圆圈,以制作类似目标的图像:

该图像必须具有一定程度的透明度。整个形状的透明度必须相同。然后,有任意数量的这些形状可以重叠,并且它需要看起来像这样:

无论重叠多少,透明度量都必须保持相同。

我唯一能想到的解决方案是迭代画布上的每个像素,并根据像素与每个圆中心的距离计算该像素应该是什么颜色,但这需要很长时间。我希望圆圈也可以拖动,所以这需要非常快。有一个更好的方法吗? (抱歉我的 GIMP 技术很差)


可以在不使用像素操作或任何库的情况下本地完成。

假设所有圆圈的透明度都相同,那就非常简单了。

Solution

snapshot
Circles on top of some random background

您需要做的是:

  • 分配一个离屏画布,其中圆圈被绘制为实心(无透明度)
  • 分三步画圆。
  • 首先是所有圆圈的红色表面,然后是所有圆圈的蓝色表面,依此类推。
  • 设置主(可见)画布透明度的全局 Alpha
  • 清除两个画布
  • 将屏幕外画布绘制到主画布上

你的圆形函数可能看起来像这样:

function drawCircle(x, y, r, step) {

    ctx.beginPath();

    switch (step) {
        case 0:  // step 0, outer circle red
            ctx.fillStyle = '#f00';
            break;

        case 1:  // step 1, middle circle blue
            ctx.fillStyle = '#00f';
            r *= 0.67;
            break;

        case 2:  // step 2, inner circle green
            ctx.fillStyle = '#0f0';
            r *= 0.33;
            break;
    }
    ctx.arc(x, y, r, 0, 2 * Math.PI);
    ctx.fill();
}

该函数取x and y中心点以及radius。但除此之外还需要一个step0 到 2 之间的值决定绘制哪个表面。这在接下来的步骤中非常重要。

首先我们可以定义一个数组来保存我们想要绘制的所有圆圈:

var circs = [
    //x   y    r   dx dy (the last two for animation only)
    [100, 100, 50, 2, 1],
    [200, 200, 50, -2, -3],
    [150, 50, 50, 3, -1]
];

从这里您可以拖动它们,偏移 x 和 y,然后重新绘制它们,但为了演示,我将为它们设置动画。

在绘制之前,我们在主画布上设置全局 Alpha(屏幕外保持不变):

mctx.globalAlpha = 0.7;  // main canvas

和动画循环:

function start() {
    
    // clear off-screen canvas
    ctx.clearRect(0,0, w, h);

    // clear main canvas
    mctx.clearRect(0,0, w, h);

    var t = 0, i, c;

    // outer step loop
    for(; t < 3; t++) {

        // draw all circles at current step
        for(i = 0; c = circs[i]; i++) {
            drawCircle(c[0], c[1], c[2], t);
        }
    }

    // re-position circles for animation
    for(i = 0;c = circs[i]; i++) {
        c[0] += c[3];  /// add delta to x
        c[1] += c[4];  /// add delta to y

        // reverse deltas if at boundaries
        if (c[0] < 0 || c[0] > w) c[3] = -c[3];
        if (c[1] < 0 || c[1] > h) c[4] = -c[4];
    }

    // draw off-screen to main canvas        
    mctx.drawImage(ocanvas, 0, 0);

    // loop animation
    requestAnimationFrame(start);
}

如果您想要将其他元素绘制到画布上,或者使用第二个屏幕画布来保存静态内容,则可以为每个操作重置全局 Alpha。

Demo

var demo = document.getElementById("demo");
var w = demo.width, h = demo.height;

var ocanvas = document.createElement('canvas');
ocanvas.width = w;
ocanvas.height = h;

var ctx = ocanvas.getContext('2d');
var mctx = demo.getContext('2d');
var img = document.createElement('img')
img.onload = start;
img.src = 'http://i.imgur.com/CHPdL2y.png';

/// key to it all
mctx.globalAlpha = 0.7;

var circs = [
    //x   y    r   dx   dy
    [100, 100, 50,  2  ,  1.5],
    [200, 200, 70, -2  , -3],
    [150,  50, 50,  3  , -1],
    [150,  50, 30,  4  ,  4],
    [150,  50, 20, -3  , -2],
    [100, 100, 55,  2.5,  2.5],
    [200, 200, 75, -1  , -2.5],
    [150,  50, 45,  3.5, -2],
    [150,  50, 35,  5  ,  2],
    [150,  50, 25, -1.2, -5]
];

function drawCircle(x, y, r, step) {

    ctx.beginPath();

    switch (step) {
        case 0:
            ctx.fillStyle = '#f00';
            break;
        case 1:
            ctx.fillStyle = '#00f';
            r *= 0.67;
            break;
        case 2:
            ctx.fillStyle = '#0f0';
            r *= 0.33;
            break;
    }
    ctx.arc(x, y, r, 0, 2 * Math.PI);
    ctx.fill();
}

function start() {
    
    ctx.clearRect(0, 0, w, h);
    mctx.clearRect(0, 0, w, h);

    var i = 0, t, c;
    for(t = 0; t < 3; t++) {
        for(i = 0; c = circs[i]; i++) {
            drawCircle(c[0], c[1], c[2], t);
        }
    }

    for(i = 0;c = circs[i]; i++) {
        c[0] += c[3];
        c[1] += c[4];
        if (c[0] < 0 || c[0] > w) c[3] = -c[3];
        if (c[1] < 0 || c[1] > h) c[4] = -c[4];
    }
    
    mctx.drawImage(ocanvas, 0, 0);
    requestAnimationFrame(start);
}
body {
    margin:0;
    background:url(//i.stack.imgur.com/b8eCZ.jpg) no-repeat;
}
<canvas id="demo" width="500" height="333"></canvas>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Alpha 通道绘制重叠的圆圈 的相关文章

  • 为什么对于大于 65776 像素的画布源,drawImage 性能差异很大

    我在 jsperf 上写了一些与以下相关的测试用例 1 在屏幕外画布上绘图 2 将图像绘制到屏幕画布上 我发现如果源画布中的像素数 无论 dst 小于 65776 像素 性能会高得多 我预计这个性能限制是 65536 像素 如果有的话 He
  • 黑色左/右三角形大小不同

    我使用黑色左指三角形 右左指三角形几何形状作为网站上的链接 并使用它们的 HTML 代码 和 9664 9654 由于某种原因 即使我在没有其他元素的空白页面上使用三角形 它们也不会以相同的大小显示 在 Chrome 上 向左指向的位置比向
  • 使用 css resize:both 调整表格单元格的大小;不使用表

    使用 css resize both 调整表格单元格大小不适用于表格 我需要调整表格及其单元格的大小 可以使用 css 调整大小 css resize both 在 div 中有效 但在表标签中无效 table border 1 tr td
  • 可以在 IE 中的表格行上添加渐变吗?

    当我将鼠标悬停在表格特定部分的表格行上时 我希望背景更改为线性渐变 CSS 很简单 tbody row links tr hover background typical multi browser linear gradient code
  • Django:单击按钮加载另一个模板

    我已经在 django 项目上工作了几个星期 只是玩玩以便掌握它的窍门 我有点困惑 我现在有一个名为 home html 的模板 我想知道是否可以将另一个名为 profile html 的模板设置为 home html 模板上的链接 我有一
  • JavaScript 中的 jstl

    可以在javascript中使用jstl吗 我正在绑定设置
  • 如何使用递归字符串连接构建带有小计的 HTML 表?

    我有接下来的两张表 CREATE TABLE SalesByStore Brand VARCHAR 10 StoreName VARCHAR 50 Sales DECIMAL 10 2 CREATE TABLE SalesByBrand B
  • 如何求小于给定数的最大2次方

    我需要找到小于给定数字的最大 2 次幂 我陷入困境 找不到任何解决方案 Code public class MathPow public int largestPowerOf2 int n int res 2 while res lt n
  • Firefox 上的 Angular JS 输入日期

    我有这些输入和这个模型
  • CSS Font-Face url 不起作用?

    我在使用 font face 选择器时遇到了一些问题 我有以下问题 font face font family MuseoSans 700 src url http mysite co uk clients reload Images st
  • 如何在 Safari 上打开本地 html 文件?

    我想打开本地 html 文件Safari集成到我的Swift 3应用 我知道如何使用网址来做到这一点 这是我用来执行此操作的代码 let encodedString url addingPercentEncoding withAllowed
  • 监听服务响应 JavaScript

    背景 我正在为网页制作 Chrome 扩展程序 在此网页中 我需要捕获用户发出 POST 请求时服务器发送的响应 目前 我们使用观察者模式来检查 HTML 页面上的更改 但这很笨拙并且会触发多次 客观的 我需要捕获该响应 相应地解析其信息
  • 如何使用 jQuery 在按下按钮后保持按钮处于活动状态

    我见过一些非常相似的问题 但一直无法找到我正在寻找的答案 我已经确定了解决方法 但想知道执行该任务的正确方法 我想要的是单击按钮并使活动状态保持不变 下一次单击将切换状态 这是所需的 我真正需要知道的是如何解决 uiButton activ
  • Karasuba算法递归过多

    我正在尝试用 c 实现 Karasuba 乘法算法 但现在我只是想让它在 python 中工作 这是我的代码 def mult x y b m if max x y lt b return x y bm pow b m x0 x bm x1
  • 如何从 Javascript/Typescript 中的数组对象计算运行总计并使用 HTML 在每个实例上显示输出?

    我正在开发一个 MEAN 堆栈项目 并且有一个如下所示的数组 savings any 300 450 350 500 我还有一个名为 saving bf 的变量 它是从数据库中检索的结转储蓄 其值如下 savings bf 15000 我想
  • 如何在 HTML 表格上使用分页?

    我正在尝试使用这个分页library http flaviusmatis github io simplePagination js 在我的 HTML 表格页面 特别是浅色主题 中 但不知何故 我无法理解如何在我的 HTML 页面中以这种方
  • IE8 中空 div 层的 z-index 问题

    我在 IE8 中遇到 z index 问题 其他尚未测试 以下 JS 创建一些 html css document write img src border 0 document write div style background col
  • Intro.js 2页然后返回首页

    我在用intro js http introjs com 为我的网站创建一个小介绍 我希望游览从第 1 页 主页 2 另一页 然后回到第 1 页 主页 我已经成功地从第 1 2 页开始 但不确定如何让它返回到第 1 页 我对 javascr
  • Onblur 事件在另一个 div 的 onclick 之前触发

    如上所述 我有一个按钮 单击该按钮将打开子菜单 对于子菜单中的每个选项 都有三个元素 我认为实际上还有更多元素 但为了简单起见 将其保留为 3 我将焦点放在子菜单的主 div 白色 框架 上 Onblur 这个 div 然后我隐藏子菜单 这
  • 用 Beautiful Soup 进行抓取:为什么 get_text 方法不返回该元素的文本?

    最近我一直在用 python 开发一个项目 其中涉及抓取一些网站的一些代理 我遇到的问题是 当我尝试抓取某个知名代理站点时 当我要求 Beautiful Soup 查找 IP 在代理表中的位置时 它并没有按照我的预期执行操作 我将尝试查找每

随机推荐

  • 将多维数组转换为字符串并返回

    我有一个二维数组 我需要能够将其转换为字符串表示形式并返回数组格式 我想创建一个通用方法来处理任何数组 1d 2d 3d 等 这样我将来就可以重用该方法 解决这个问题的最佳方法是什么 string array new string help
  • 手动添加声明文件 (TypeScript)

    我没有找到 google spreadsheet 的声明文件 因此我尝试自己创建一个 在打字 gt 模块中 我添加了一个名为 google spreadsheet 的新文件夹 并在其中添加了一个名为 index d ts 的新文件 其中包含
  • 更新 Spring 注入的属性文件以包含上次运行时间戳

    我有一个应用程序 它使用 Spring 加载的属性文件 然后将 Properties 实例注入到几个类中 问题是其中一些属性已更新 例如我们有一个要存储在这里的lastRun时间戳 也许有更好的方法来存储这样的东西 欢迎建议 但是我该如何更
  • 对于具有相同分数的文档,主/副本的结果顺序不一致

    我创建了一个包含单个分片和 1 个副本的索引 我正在运行 ElasticSearch 版本 1 0 1 并且集群有 3 个节点 我注意到 有时具有相同分数的文档的结果排序是 根据是否针对主数据库和副本数据库运行相同的查询而有所不同 该查询是
  • 从 System.Windows.Media.Geometry 获取坐标列表

    Given a System Windows Media Geometry类实例 有没有一种简单的方法可以将其转换为轮廓和点列表 例如 我怎样才能简单地将其分解为一个列表LineSegments用于自定义渲染 FormattedText f
  • “springSecurityFilterChain”抛出异常;嵌套异常是 java.lang.IllegalArgumentException:提供程序列表不能包含空值

    在启动 SpringBoot 应用程序时 我不断收到以下错误 与我有关吗SpringWebSecurityConfig文件 以下是文件内容 Configuration public class SpringWebSecurityConfig
  • 如何从 System.Windows.Input.KeyEventArgs 获取按下的字符?

    I have System Windows Input KeyEventArgse 变量 我想得到真正的字符 例如 我按 键盘上的按钮 通常它会返回类似的字符串oem 但我想得到 字符 怎么做 编辑 我在 TextBox 中使用它 看到这个
  • 为什么加载后命令提示符消失了?

    使用下面的代码 命令提示符几乎在出现后立即消失 此代码不应该显示正在使用的所有可移动驱动器吗 using System Linq using System IO using System namespace ConsoleApplicati
  • 通过 cron 发布到 Facebook

    两天来我一直在尝试将从 Twitter 搜索收集的消息自动发布到我的 Facebook 页面之一 即通过 cronjob twitter 部分运行得很好 但我怎么也无法让 Facebook 部分工作 问题是我的脚本可以工作 直到它不能工作
  • Visual Studio 代码未加载我的 python 解释器

    在这个项目中 我一直在使用我在 venv 中设置的 python 解释器 最近我更改了我的 python 解释器 我在用户设置中将其设置为默认解释器 例如 vs 文档vs code python 环境 https code visualst
  • EXC_BAD_ACCESS 使用 IBInspectable

    我正在尝试使用IBInspectable为我的视图添加边框 extension UIView private func getBorder integer Int gt UIRectEdge if integer 1 return top
  • 在 forEach 之后发送响应

    请注意 这不是两个类似标题问题的重复 这两个问题使用 Mongoose 并且答案仅适用于 Mongoose 查询 我有一个目录列表 每个目录都包含一个文件 我想返回一个 JSON 列表 其中包含每个文件的内容 我可以毫无问题地加载文件 但是
  • Python 检查值是否在字典列表中

    我有一个字典列表 例如 name Bernard age 7 name George age 4 name Reginald age 6 我想检查字符串值是否与列表中任何字典中的 名称 值相同 例如 Harold 将为 False 但 Ge
  • XMPP:检索 BOSH 会话 ID 和 RID

    请告诉我如何检索 SID 和 JID 我正在使用 Strope JS var conn new Strophe Connection bosh service 然而 conn sid or conn rid没有返回相同的数字 经过这个和那个
  • 尝试获取字段值时出现属性错误

    我正在使用 django 休息框架 并且我尝试使用的序列化器正在创建错误 我正在尝试做类似的事情https gist github com anonymous 7463dce5b0bfcf9b6767 https gist github c
  • 在不耗尽 RAM 的情况下使用并发 Future

    我正在做一些文件解析 这是一个 CPU 密集型任务 无论我向该进程放入多少文件 它使用的 RAM 都不会超过 50MB 该任务是可并行的 我已将其设置为使用下面的并发 future 将每个文件解析为单独的进程 from concurrent
  • 在Java中写入文本文件而不覆盖

    我正在尝试编写一种方法 如果 log txt 文件 尚不存在 则创建一个 log txt 文件 然后写入该文件 我遇到的问题是每次调用该方法时 它都会覆盖现有日志 如何更改方法 以便不覆盖数据而只更新文件 我的写入文件方法 File log
  • DataTable - 使可滚动,设置背景颜色并修复/冻结标题行和第一列

    我开始在 Flutter 中使用 webview 图表 表格进行开发 但是我遇到了一些表格问题 I use 数据表来表示表中的数据 有第一个问题 默认情况下 如果数据超出屏幕 则它不可滚动 所以我嵌入了一些小部件 即 SingleChild
  • 如何输入提示

    我如何输入提示来摆脱剩余的反射调用 def B amap D A i D B amap doubles aget A int i j doubles row 2 aget row int j 还剩下两个反射调用 但我不知道如何摆脱它们 您没
  • 使用 Alpha 通道绘制重叠的圆圈

    这个问题已经在这里得到了回答 重叠圆的组合面积 https stackoverflow com questions 1667310 combined area of overlapping circles 不过我的问题更具体 我在其他任意大