You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
对于碰撞,我使用了 point within radius 模块判断顶点是否与鼠标发生碰撞。该碰撞检测的运算速度很快,但并非完美:叶子上存在部分“盲点”,即不会产于交互。为了在划动叶子时产生更精确的声音效果,我在小树叶上使用 point to line segment distance 进行碰撞检测。使用后者能产生更佳的互动体验,但在最终案例中,较大的鼠标半径和较多的植物数量使得难以发现两者差异。
在开发期间,我使用 dat.gui 作为可视化滑块,并使用 surge.sh 与团队的其他成员共享迭代。这些工具使得我们能够尝试许多不同的想法和方向。而这种开发迭代的方式也让我们能想出一些有趣的特性:直到项目后期我们才引入了在黑色“手绘”状态下添加动画的想法(译者注:此句原文为:it wasn’t until later in the project that we introduced the idea of animating plants in from a black “hand-drawn” state)。
原文:Leaf Notes – An Interactive Web Toy
在浏览器上体验 https://tendril.ca/
我最近为多伦多的设计动画工作室 Tendril 推出了一个可互动的 Web 小玩具。你可以在其 官网首页 亲自体验。该网站会轮流展示数个不同的 Web 玩具,所以可能需要刷新一到两次才能看到它。
<iframe src="https://player.vimeo.com/video/261147357" width="640" height="367" frameborder="0" allowfullscreen></iframe>玩法非常简单:用鼠标划过植物就能使它们开花,并发出相应音调。
该项目十分有趣,我对目前结果也非常满意。Twitter 和 Instagram 上的热烈反应使我备受鼓舞,其中最让我暖心的是一位年仅四岁的小孩在平板上进行了体验。
本文将阐述我与优秀团队 Tendril 如何创造这个 Web 玩具,并讨论期间遇到的一些技术挑战。
概念
在前一段时间,Tendril 已在其官网推出了独具一格的交互动画(案例:1、2)。他们想让我创造一种全新的体验,且要体现生殖生长和程序化几何。
Tendril 先前的一个 Web 玩具
这个想法十分开放:为 Tendril 官网开发一个可互动的有趣玩具。它与已有的 Web 玩具共存,所以设计要适中、使用要简单、加载速度要快。总的来说:交互方式要轻易上手,整体体验要与 Tendril 的网站一致。
一个充满创作自由的想法对我来说可是一个挑战。在过去几个月里,我一直逼自己在开发前进行更多的搜索、头脑风暴、艺术指导和设计思考和构思。我发现铅笔和笔记本确实是最好的工具,不过像 Pinterest 和 Behance 这类平台则有助于管理参考文献和寻找灵感来源。
在讨论了几个不同想法后,我们选定了“与热带植物交互”的这个方向。
早期 情绪板
我早期的情绪板更倾向于单色而鲜明的视觉方向。这些信息反映出了项目在迭代开发中的变化区间。
植物的生殖生长
早期程序化生化的植物几何体 Canvas2D 原型
最初,我使用 Canvas2D 的线来进行植物结构的原型设计。这无疑是快速验证想法和几何实现的好方法,因为这无需关心 WebGL 和 GPU 的复杂性。
我使用了简单的线段和二次贝塞尔曲线建立了植物的程序结构。二次贝塞尔曲线如下图所示,它由起点、控制点和终点构成。
使用简单的基本图形和参数函数(如线、曲线)能让事情变得更可控,如动画、GPU 的快速渲染、鼠标的碰撞检测、甚至是声音设计等。例如:定义变量 t,它是 [0, 1] 区间的数字,然后使用参数函数高效地计算出该值所代表的 2D 点。
结构
为每棵植物定义一个起点(如屏幕边界)和一个终点(如接近屏幕中点的某个位置)。然后,再放置一个稍微偏离两端点间中点的控制点,以形成一种弯曲植物茎的感觉。
为生成叶子,需按固定间隔遍历曲线,确定每个位置上的垂直法向量,并使用一些函数对法向量进行缩放 & 旋转操作,最终形成像“羽毛”一样的叶子。在最终案例中,我并未使用垂直法向量,而是使用了斜接的法向量(mitered normal)【译者注:mitered normal 翻译有误】。
我提取部分代码到以下 Canvas2D 案例中,你可以在 这里 查看/修改。点击以下案例可修改曲线结构。
学习到的错误及经验教训
在 2D 原型设计阶段,我犯了两个错误。在后续原型设计中应尽量避免:
动画 & 交互
在几何植物的顶点上使用简单的弹簧效果,而不是使用复杂且 CPU 密集型的物理系统。这使得植物看起来有点像果冻,但不失为一个有趣好玩的互动。
对植物茎和叶子上的顶点,我都指定了
target
(即顶点应该弹向的目标位置)、position
(即顶点的实时位置)和velocity
(速度和运动方向)。基础物理系统的伪代码如下:以下是顶点弹簧效果的交互案例,它展示了如何让二次贝塞尔曲线与鼠标产生弹簧的效果。尝试一下案例吧,也可以 点击这里 阅读完整代码:
对于碰撞,我使用了 point within radius 模块判断顶点是否与鼠标发生碰撞。该碰撞检测的运算速度很快,但并非完美:叶子上存在部分“盲点”,即不会产于交互。为了在划动叶子时产生更精确的声音效果,我在小树叶上使用 point to line segment distance 进行碰撞检测。使用后者能产生更佳的互动体验,但在最终案例中,较大的鼠标半径和较多的植物数量使得难以发现两者差异。
渲染
尽管 Canvas2D 能很好地完成原型阶段的处理,但却不能胜任诸如逐像素着色的工作。
感谢 ThreeJs 及其
OrthographicCamera
,它们使得所有 canvas 代码迁移至 WebGL 变得不会太难。每根植物茎由一个PlaneGeometry
(可复用)和一个自定义顶点着色器(vertex shader)组成。顶点着色器将平面几何段(plane segments)沿曲线(或线段,即植物茎或叶子)放置。可通过我之前编写的笔记 《2D Quadratic Curves on the GPU》 了解更多该技术相关的知识点。通过该方法能生成每棵植物所需的曲线和线段。最终效果如下:
在顶点着色器中,我添加了参数函数,以实现沿 t 弧长变化的线宽。例如:
thickness = sin(t * PI)
会压缩曲线的开始和结束部分。有了这些函数,平面几何的轮廓开始变得更像锥形叶子。最后,添加颜色和外观细节——每片叶子在亮度、色相、饱和度、叶脉密度和旋转角度等方面均有了细微变化。所有这些计算均在片段着色器(fragment shader)完成。例如:每片叶子的叶脉和中线是基于纹理坐标计算得到的,并使用
fwidth()
计算出抗齿锯 2~3 像素的平滑曲线。在开发期间,我使用 dat.gui 作为可视化滑块,并使用 surge.sh 与团队的其他成员共享迭代。这些工具使得我们能够尝试许多不同的想法和方向。而这种开发迭代的方式也让我们能想出一些有趣的特性:直到项目后期我们才引入了在黑色“手绘”状态下添加动画的想法(译者注:此句原文为:it wasn’t until later in the project that we introduced the idea of animating plants in from a black “hand-drawn” state)。
小细节
为了让项目更加生意盎然,我在小细节上花费了许多时间。实际上,叶子的核心结构和弹簧般的交互效果是最简单的部分,而大部分时间则花在了提升视觉效果、制作动画和修复各种跨浏览器问题上。
部分细节如下:
最后的障碍
和一般交互式 Web 项目一样,项目的最后阶段通常需要小调整,以确保能在各类浏览器和设备上顺利运行。
对此,我使用了几个过去用于处理常见跨浏览器问题的模块,如用于统一鼠标和触摸事件的 touches 和兼容 iOS WebAudio 的 web-audio-player。
还有其他一些浏览器问题,以下是我处理的方案:
setTimeout
不能及时触发回调函数。因此,我认为它是不精确的,而且我也不可能为此等待 2~3 秒之久。于是选择 timeout-raf 修复它。audioContext.resume()
。window.innerWidth
值。为了修复该问题,我最终为canvas
设置position:fixed
且宽高 100% 的样式。作者
感谢 Tendril 团队,名单如下:
本文和交互案例的源码均可在以下链接找到:
https://github.com/mattdesl/tendril-webtoy-blog-post
The text was updated successfully, but these errors were encountered: