Paper.js 实现动态Voronoi图交互效果技术解析

Paper.js 实现动态Voronoi图交互效果技术解析

paper.js The Swiss Army Knife of Vector Graphics Scripting – Scriptographer ported to JavaScript and the browser, using HTML5 Canvas. Created by @lehni & @puckey paper.js 项目地址: https://gitcode.com/gh_mirrors/pa/paper.js

前言

Voronoi图(沃罗诺伊图)是计算几何中的一个重要概念,它将平面划分为多个区域,每个区域包含一个种子点,区域内任意一点到该种子点的距离都小于到其他种子点的距离。在Paper.js中,我们可以利用其强大的矢量图形处理能力,结合Voronoi算法库,创建出精美的交互式Voronoi图效果。

核心实现原理

1. 初始化设置

首先需要引入Voronoi算法库和Paper.js库。代码中创建了Voronoi实例,并初始化了一些关键变量:

var voronoi = new Voronoi();
var sites = generateBeeHivePoints(view.size / 200, true);
var bbox, diagram;
var oldSize = view.size;
var spotColor = new Color('red');
var mousePos = view.center;
var selected = false;

2. 蜂巢点生成算法

generateBeeHivePoints函数生成初始的种子点分布,采用蜂巢状排列方式:

function generateBeeHivePoints(size, loose) {
    var points = [];
    var col = view.size / size;
    for (var i = -1; i < size.width + 1; i++) {
        for (var j = -1; j < size.height + 1; j++) {
            var point = new Point(i, j) / new Point(size) * view.size + col / 2;
            if (j % 2)
                point += new Point(col.width / 2, 0);
            if (loose)
                point += (col / 4) * Point.random() - col / 4;
            points.push(point);
        }
    }
    return points;
}

这个算法特点:

  • 创建规则的网格点
  • 奇数行偏移半个单位,形成蜂巢结构
  • 可选的随机扰动使分布更自然

3. Voronoi图渲染流程

核心渲染函数renderDiagram完成以下工作:

  1. 清空画布
  2. 计算Voronoi图
  3. 遍历每个种子点的Voronoi单元
  4. 为每个单元创建路径
function renderDiagram() {
    project.activeLayer.removeChildren();
    var diagram = voronoi.compute(sites, bbox);
    if (diagram) {
        for (var i = 0, l = sites.length; i < l; i++) {
            var cell = diagram.cells[sites[i].voronoiId];
            if (cell) {
                var halfedges = cell.halfedges,
                    length = halfedges.length;
                if (length > 2) {
                    var points = [];
                    for (var j = 0; j < length; j++) {
                        v = halfedges[j].getEndpoint();
                        points.push(new Point(v));
                    }
                    createPath(points, sites[i]);
                }
            }
        }
    }
}

4. 路径创建与优化

createPath函数负责将Voronoi单元的顶点转换为平滑的Paper.js路径:

function createPath(points, center) {
    var path = new Path();
    path.fillColor = selected ? null : spotColor;
    path.fullySelected = selected;
    path.closed = true;

    for (var i = 0, l = points.length; i < l; i++) {
        var point = points[i];
        var next = points[(i + 1) == points.length ? 0 : i + 1];
        var vector = (next - point) / 2;
        path.add({
            point: point + vector,
            handleIn: -vector,
            handleOut: vector
        });
    }
    path.scale(0.95);
    removeSmallBits(path);
    return path;
}

关键技术点:

  • 使用贝塞尔曲线处理顶点,使边缘更平滑
  • 整体缩放95%产生间隙效果
  • removeSmallBits函数移除过小的线段保持图形整洁

交互功能实现

1. 鼠标交互

function onMouseDown(event) {
    sites.push(event.point);
    renderDiagram();
}

function onMouseMove(event) {
    mousePos = event.point;
    if (event.count == 0)
        sites.push(event.point);
    sites[sites.length - 1] = event.point;
    renderDiagram();
}
  • 点击添加新种子点
  • 移动鼠标动态更新最后一个种子点位置

2. 视图响应

function onResize() {
    var margin = 20;
    bbox = {
        xl: margin,
        xr: view.bounds.width - margin,
        yt: margin,
        yb: view.bounds.height - margin
    };
    for (var i = 0, l = sites.length; i < l; i++) {
        sites[i] = sites[i] * view.size / oldSize;
    }
    oldSize = view.size;
    renderDiagram();
}
  • 自适应窗口大小变化
  • 保持种子点相对位置不变

3. 键盘交互

function onKeyDown(event) {
    if (event.key == 'space') {
        selected = !selected;
        renderDiagram();
    }
}
  • 空格键切换显示模式(填充色/描边)

应用场景与扩展

这种动态Voronoi图实现可以应用于:

  1. 艺术创作:生成有机形态的艺术图案
  2. 游戏开发:地图区域划分、势力范围可视化
  3. 数据可视化:空间数据分区展示
  4. 交互设计:创新的用户界面元素

扩展思路:

  • 添加动画效果,如种子点缓动
  • 实现种子点的拖拽交互
  • 结合物理引擎模拟细胞分裂效果
  • 使用图像数据驱动种子点分布

总结

通过Paper.js实现Voronoi图展示了矢量图形库与计算几何算法的完美结合。这种技术组合不仅能够创建美观的视觉效果,还为各种创意应用提供了坚实的基础。理解这个示例的实现原理,可以帮助开发者掌握Paper.js的高级用法,并启发更多创新的可视化解决方案。

paper.js The Swiss Army Knife of Vector Graphics Scripting – Scriptographer ported to JavaScript and the browser, using HTML5 Canvas. Created by @lehni & @puckey paper.js 项目地址: https://gitcode.com/gh_mirrors/pa/paper.js

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

水鲁焘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值