我正在寻找一种在 Canvas 中设计的形状中创建波浪的方法。经过大量研究,我发现了一些非常接近我想要的东西:
var c = document.getElementById('c'),
ctx = c.getContext('2d'),
cw = c.width = window.innerWidth,
ch = c.height = window.innerHeight,
points = [],
tick = 0,
opt = {
count: 5,
range: {
x: 20,
y: 80
},
duration: {
min: 20,
max: 40
},
thickness: 10,
strokeColor: '#444',
level: .35,
curved: true
},
rand = function(min, max) {
return Math.floor((Math.random() * (max - min + 1)) + min);
},
ease = function(t, b, c, d) {
if ((t /= d / 2) < 1) return c / 2 * t * t + b;
return -c / 2 * ((--t) * (t - 2) - 1) + b;
};
ctx.lineJoin = 'round';
ctx.lineWidth = opt.thickness;
ctx.strokeStyle = opt.strokeColor;
var Point = function(config) {
this.anchorX = config.x;
this.anchorY = config.y;
this.x = config.x;
this.y = config.y;
this.setTarget();
};
Point.prototype.setTarget = function() {
this.initialX = this.x;
this.initialY = this.y;
this.targetX = this.anchorX + rand(0, opt.range.x * 2) - opt.range.x;
this.targetY = this.anchorY + rand(0, opt.range.y * 2) - opt.range.y;
this.tick = 0;
this.duration = rand(opt.duration.min, opt.duration.max);
}
Point.prototype.update = function() {
var dx = this.targetX - this.x;
var dy = this.targetY - this.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (Math.abs(dist) <= 0) {
this.setTarget();
} else {
var t = this.tick;
var b = this.initialY;
var c = this.targetY - this.initialY;
var d = this.duration;
this.y = ease(t, b, c, d);
b = this.initialX;
c = this.targetX - this.initialX;
d = this.duration;
this.x = ease(t, b, c, d);
this.tick++;
}
};
Point.prototype.render = function() {
ctx.beginPath();
ctx.arc(this.x, this.y, 3, 0, Math.PI * 2, false);
ctx.fillStyle = '#000';
ctx.fill();
};
var updatePoints = function() {
var i = points.length;
while (i--) {
points[i].update();
}
};
var renderPoints = function() {
var i = points.length;
while (i--) {
points[i].render();
}
};
var renderShape = function() {
ctx.beginPath();
var pointCount = points.length;
ctx.moveTo(points[0].x, points[0].y);
var i;
for (i = 0; i < pointCount - 1; i++) {
var c = (points[i].x + points[i + 1].x) / 2;
var d = (points[i].y + points[i + 1].y) / 2;
ctx.quadraticCurveTo(points[i].x, points[i].y, c, d);
}
ctx.lineTo(-opt.range.x - opt.thickness, ch + opt.thickness);
ctx.lineTo(cw + opt.range.x + opt.thickness, ch + opt.thickness);
ctx.closePath();
ctx.fillStyle = 'hsl(' + (tick / 2) + ', 80%, 60%)';
ctx.fill();
ctx.stroke();
};
var clear = function() {
ctx.clearRect(0, 0, cw, ch);
};
var loop = function() {
window.requestAnimFrame(loop, c);
tick++;
clear();
updatePoints();
renderShape();
//renderPoints();
};
var i = opt.count + 2;
var spacing = (cw + (opt.range.x * 2)) / (opt.count - 1);
while (i--) {
points.push(new Point({
x: (spacing * (i - 1)) - opt.range.x,
y: ch - (ch * opt.level)
}));
}
window.requestAnimFrame = function() {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(a) {
window.setTimeout(a, 1E3 / 60)
}
}();
loop();canvas {
display: block;
}<canvas id="c"></canvas>
http://codepen.io/jackrugile/pen/BvLHg
问题是波浪的运动看起来有点不真实。我想保留这种随机运动的概念,而不是通过从左向右移动来重复自己的形状,但是如果我找到一种方法来创建“逼真的”水运动(良好的流体动力学,碰撞这个波浪及其容器的边缘(自定义形状))。
我想我问了很多但是......一小部分研究可能会有所帮助:)
最佳答案
您可以使用干涉来制作更逼真的波浪。
使用各种参数,以便您可以实时调整它以找到一个好的组合。
您还可以添加振荡器来表示 z 轴,以使其更加逼真,以防您想要将波分层以制作伪 3D 波。
我不能给你波浪碰撞、流体动力学——这对 SO 来说有点太宽泛了,但我可以给你一个流体波的例子(因为你有每个部分的点,你可以用它来进行碰撞检测) .
示例是创建一个振荡器对象,您可以在该对象上设置各种设置,例如振幅、旋转速度(相位)等。
然后有一个混频器功能,可以混合您使用的这些振荡器的结果。
此演示中的振荡器对象如下所示:
function osc() {
/// various settings
this.variation = 0.4; /// how much variation between random and max
this.max = 100; /// max amplitude (radius)
this.speed = 0.02; /// rotation speed (for radians)
var me = this, /// keep reference to 'this' (getMax)
a = 0, /// current angle
max = getMax(); /// create a temp. current max
/// this will be called by mixer
this.getAmp = function() {
a += this.speed; /// add to rotation angle
if (a >= 2.0) { /// at break, reset (see note)
a = 0;
max = getMax();
}
/// calculate y position
return max * Math.sin(a * Math.PI) + this.horizon;
}
function getMax() {
return Math.random() * me.max * me.variation +
me.max * (1 - me.variation);
}
return this;
}
这会为我们完成所有设置和计算,我们需要做的就是调用 getAmp() 为每一帧获取一个新值。
我们可以使用“混合器”代替手动操作。这个混音器允许我们添加任意数量的振荡器到混音中:
function mixer() {
var d = arguments.length, /// number of arguments
i = d, /// initialize counter
sum = 0; /// sum of y-points
if (d < 1) return horizon; /// if none, return
while(i--) sum += arguments[i].getAmp(); /// call getAmp and sum
return sum / d + horizon; /// get average and add horizon
}
将其放入带有点记录器的循环中,点记录器会在一个方向上移动点,从而创建一个看起来很流畅的波浪。
上面的演示使用了三个振荡器。 (在这方面的一个技巧是保持旋转速度低于大浪,否则你会在上面遇到小颠簸。)
注意:我创建一个新的随机最大值的方式并不是最好的方式,因为我使用了一个断点(但对于演示目的来说很简单)。您可以用更好的东西代替它。
关于javascript - 在 Canvas 中制作波浪并制作动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19787775/
Unity自动旋转动画1.开门需要门把手先动,门再动2.关门需要门先动,门把手再动3.中途播放过程中不可以再次进行操作觉得太复杂?查看我的文章开关门简易进阶版效果:如果这个门可以直接打开的话,就不需要放置"门把手"如果门把手还有钥匙需要旋转,那就可以把钥匙放在门把手的"门把手",理论上是可以无限套娃的可调整参数有:角度,反向,轴向,速度运行时点击Test进行测试自己写的代码比较垃圾,命名与结构比较拉,高手轻点喷,新手有类似的需求可以拿去做参考上代码usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;u
动漫制作技巧是很多新人想了解的问题,今天小编就来解答与大家分享一下动漫制作流程,为了帮助有兴趣的同学理解,大多数人会选择动漫培训机构,那么今天小编就带大家来看看动漫制作要掌握哪些技巧?一、动漫作品首先完成草图设计和原型制作。设计草图要有目的、有对象、有步骤、要形象、要简单、符合实际。设计图要一致性,以保证制作的顺利进行。二、原型制作是根据设计图纸和制作材料,可以是手绘也可以是3d软件创建。在此步骤中,要注意的问题是色彩和平面布局。三、动漫制作制作完成后,加工成型。完成不同的表现形式后,就要对设计稿进行加工处理,使加工的难易度降低,并得到一些基本准确的概念,以便于后续的大样、准确的尺寸制定。四、
我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的
我有这个:AccountSummary我想单击该链接,但在使用link_to时出现错误。我试过:bot.click(page.link_with(:href=>/menu_home/))bot.click(page.link_with(:class=>'top_level_active'))bot.click(page.link_with(:href=>/AccountSummary/))我得到的错误是:NoMethodError:nil:NilClass的未定义方法“[]” 最佳答案 那是一个javascript链接。Mechan
动画/*INITIALIZEANANIMATION 初始化一个动画*-----------------------*/lv_anim_ta;lv_anim_init(&a);/*MANDATORYSETTINGS 必选设置*------------------*//*Setthe"animator"function 设置“动画”功能*/lv_anim_set_exec_cb(&a,(lv_anim_exec_xcb_t)lv_obj_set_x);/*Setthe"animator"function*/lv_anim_set_var(&a,obj);/*Lengthoftheanim
我有一个关于多维数组的初学者ruby问题。我想按年份和月份对条目进行排序。所以我想创建一个包含年->月->月条目的多维数组所以数组应该是这样的:2009->08->Entry1->Entry209->Entry32007->10->Entry5现在我有:@years=[]@entries.eachdo|entry|timeobj=Time.parse(entry.created_at.to_s)year=timeobj.strftime("%Y").to_imonth=timeobj.strftime("%m").to_itmparr=[]tmparrentry}@years.pu
我看到有关未找到文件min.map的错误消息:GETjQuery'sjquery-1.10.2.min.mapistriggeringa404(NotFound)截图这是从哪里来的? 最佳答案 如果ChromeDevTools报告.map文件的404(可能是jquery-1.10.2.min.map、jquery.min.map或jquery-2.0.3.min.map,但任何事情都可能发生)首先要知道的是,这仅在使用DevTools时才会请求。您的用户不会遇到此404。现在您可以修复此问题或禁用sourcemap功能。修复:获取文
问题总结我想尝试使用Ruby来完成我在Python中所做的事情。在Python中它有r"""syntaxtosupportrawstrings,这很好,因为它允许将原始字符串与代码内联,并以更自然的方式连接它们,而无需特殊缩进。在Ruby中,当使用原始字符串时,必须使用其次是EOT在单独的行中,这会破坏代码布局。你可能会问,为什么不使用Ruby的%q{}?嗯,因为%q{}与Python的r"""相比有局限性因为它不会转义多个\\\并且只处理单个\.我正在动态生成Latex代码并写入一个文件,该文件稍后用pdflatex编译。Latex代码包含类似\\\的内容在许多地方。如果我使用Rub
我有一个用Rails3编写的站点。我的帖子模型有一个名为“内容”的文本列。在帖子面板中,html表单使用tinymce将“content”列设置为textarea字段。在首页,因为使用了tinymce,post.html.erb的代码需要用这样的原始方法来实现。.好的,现在如果我关闭浏览器javascript,这个文本区域可以在没有tinymce的情况下输入,也许用户会输入任何xss,比如alert('xss');.我的前台会显示那个警告框。我尝试sanitize(@post.content)在posts_controller中,但sanitize方法将相互过滤tinymce样式。例如
我正在使用Ruby1.8。似乎downcase不会改变非拉丁字符。例如:"Δ".downcase返回“Δ”我知道在Ruby1.9.1及更高版本中,我可以使用UnicodeUtils(fromhere)。我试过了,它工作正常。返回上一个示例的"δ"。是否有适用于1.8Ruby的等效(或任何)解决方案? 最佳答案 nash@nash:~$ruby-vruby1.8.7(2011-02-18patchlevel334)[i686-linux]gem安装unicode(https://rubygems.org/gems/unicode)re