HTML5實驗:JavaScript模擬流體效果
把現實世界當中的物體模擬到計算機當中,一些簡單的物理實驗、碰撞旋轉等等難度還是不算很大,難度較大的應當算流體模擬。
本文將在Canvas當中模擬出一個2D平面內的水珠,涉及的知識點和技巧包括:Jscex基礎知識,貝塞爾曲線的繪製,合理利用CanvasRenderingContext2D的translate和rotate等API。
繪製橢圓
在模擬水滴之前,我們先思考一下怎麼在canvas當中繪製一個橢圓。
大家可以很容易想到 下面幾種方案:
1.根據橢圓笛卡爾座標系方程繪製
2.根據橢圓極座標方程繪製
3.根據橢圓曲率變化繪製
4.利用四條貝塞爾曲線繪製
第四中,也是效能最好的一種,這樣可以避免複雜的計算,充分利用CanvasRenderingContext2D的API(API的效能是通過嚴格測試,一般情況下比較靠譜).
所以我們採用第四種方式來繪製橢圓。
var canvas;
var ctx;
canvas = document.getElementById(“myCanvas1”);
ctx = canvas.getContext(“2d”);
ctx.strokeStyle = “#fff”;
function drawEllipse(x, y, w, h) {
var k = 0.5522848;
var ox = (w / 2) * k;
var oy = (h / 2) * k;
var xe = x + w;
var ye = y + h;
var xm = x + w / 2;
var ym = y + h / 2;
ctx.beginPath();
ctx.moveTo(x, ym);
ctx.bezierCurveTo(x, ym – oy, xm – ox, y, xm, y);
ctx.bezierCurveTo(xm + ox, y, xe, ym – oy, xe, ym);
ctx.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye);
ctx.bezierCurveTo(xm – ox, ye, x, ym + oy, x, ym);
ctx.stroke();
}
ctx.clearRect(0,0,canvas.width,canvas.height);
drawEllipse(10, 10, 40, 82);
(改變drawEllipse的四個引數試試)
旋轉橢圓
這裡的旋轉不是繞上面的drawEllipse的前兩個引數x,y旋轉,二是繞橢圓的中心旋轉。所以僅僅CanvasRenderingContext2D.rotate是不夠的,因為CanvasRenderingContext2D.rotate是繞畫布的左上角(0,0)旋轉。所以我們先要把(0,0)通過CanvasRenderingContext2D.translate到橢圓的中心,然後再drawEllipse(-a/2, –b/2, a, b).
上面這句話,就是繞中心旋轉的核心。這裡還可以推廣到任意圖形或者圖片(假設有約定的中心)。如圖:
然後我們就可以先繪製一個鳥巢出來:
<html>
<head>
<script src=”http://files.cnblogs.com/iamzhanglei/jscex.jscexRequire.min.js” type=”text/javascript”></script>
</head>
<body>
<style type=”text/css”>
input.css3btn
{
background: -moz-linear-gradient(270deg, #d2ebf8, #0c8ab5);
background: -webkit-linear-gradient(top, #d2ebf8, #0c8ab5);
background: -o-linear-gradient(top, #d2ebf8, #0c8ab5);
filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr=`#000099CC`, EndColorStr=`#FF0087B4`);
border-top: 1px solid #38538c;
border-right: 1px solid #1f2d4d;
border-bottom: 1px solid #151e33;
border-left: 1px solid #1f2d4d;
border-radius: 4px;
box-shadow: inset 0 1px 10px 1px #5c8bee, 0px 1px 0 #1d2c4d, 0 2px 0px #1f3053, 0 4px 4px 1px #111111;
color: #f0f0f0;
font: bold 20px “helvetica neue” , helvetica, arial, sans-serif;
padding: 10px 0 10px 0;
text-align: center;
text-shadow: 0px -1px 1px #1e2d4d;
width: 150px;
background-clip: padding-box;
}
input.css3btn:hover
{
box-shadow: inset 0 0px 20px 1px #87adff, 0px 1px 0 #1d2c4d, 0 3px 0px #1f3053, 0 4px 4px 1px #111111;
cursor: pointer;
}
input.css3btn:active
{
box-shadow: inset 0 1px 10px 1px #5c8bee, 0 1px 0 #1d2c4d, 0 2px 0 #1f3053, 0 4px 3px 0 #111111;
margin-top: 1px;
}
</style>
<canvas id=”myCanvas2″ width=”350″ height=”350″ style=”border: solid 15px #222; background-color: #111;
color: #CCC;”>
Your browser does not support the canvas element.
</canvas>
<script>
var canvas;
var ctx;
var px = 0;
var py = 0;
function init() {
canvas = document.getElementById(“myCanvas2”);
ctx = canvas.getContext(“2d”);
ctx.strokeStyle = “#fff”;
ctx.translate(70, 70);
}
init();
var i = 0;
function drawEllipse(x, y, w, h) {
var k = 0.5522848;
var ox = (w / 2) * k;
var oy = (h / 2) * k;
var xe = x + w;
var ye = y + h;
var xm = x + w / 2;
var ym = y + h / 2;
ctx.beginPath();
ctx.moveTo(x, ym);
ctx.bezierCurveTo(x, ym – oy, xm – ox, y, xm, y);
ctx.bezierCurveTo(xm + ox, y, xe, ym – oy, xe, ym);
ctx.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye);
ctx.bezierCurveTo(xm – ox, ye, x, ym + oy, x, ym);
ctx.stroke();
ctx.translate(x + 70, y + 100);
px = -70;
py = -100;
ctx.rotate(10 * Math.PI * 2 / 360);
}
var ct;
var drawAsync = eval(Jscex.compile(“async”, function (ct) {
while (true) {
drawEllipse(px, py, 140, 200)
$await(Jscex.Async.sleep(200, ct));
}
}))
function Button1_ {
ct.cancel();
}
function Button2_ {
ct = new Jscex.Async.CancellationToken();
drawAsync(ct).start();
}
</script>
<br />
<input id=”Button2″ class=”css3btn” type=”button” value=”run” Button2_ />
<input id=”Button1″ class=”css3btn” type=”button” value=”stop” Button1_ />
</body>
</html>
繪製水滴
旋轉的橢圓和鳥巢神馬的和水滴有什麼關係呢?
我們通過改變橢圓的長軸和短軸,令其非常接近圓形(只能接近,不能等於圓形),然後每次旋轉擦除畫布,就可以達你預想不到的效果!
這裡需要注意的是,擦除畫布不再是一句CanvasRenderingContext2D.clearRect(0,0,canvas.width,canvas.height)就可以,因為畫布已經旋轉和畫布原點已經translate,所以我們使用 ctx.clearRect(-canvas.width, -canvas.height, 2 * canvas.width, 2 * canvas.height)來擦除畫布。
我們畫一個長軸42,短軸40的橢圓,旋轉並擦除畫布:
function drawEllipse(x, y, w, h) {
ctx.clearRect(-canvas.width, -canvas.height, 2 * canvas.width, 2 * canvas.height);
var k = 0.5522848;
var ox = (w / 2) * k;
var oy = (h / 2) * k;
var xe = x + w;
var ye = y + h;
var xm = x + w / 2;
var ym = y + h / 2;
ctx.beginPath();
ctx.moveTo(x, ym);
ctx.bezierCurveTo(x, ym – oy, xm – ox, y, xm, y);
ctx.bezierCurveTo(xm + ox, y, xe, ym – oy, xe, ym);
ctx.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye);
ctx.bezierCurveTo(xm – ox, ye, x, ym + oy, x, ym);
ctx.stroke();
ctx.translate(x + 20, y + 21);
px = -20;
py = -21;
ctx.rotate(10 * Math.PI * 2 / 360);
}
var ct;
var drawAsync = eval(Jscex.compile(“async”, function (ct) {
while (true) {
drawEllipse(px, py, 40, 42)
$await(Jscex.Async.sleep(10, ct));
}
}))
會是什麼效果呢?
線上演示效果檢視http://www.cnblogs.com/iamzhanglei/archive/2011/12/12/2284188.html
相關文章
- JavaScript模擬拋物效果JavaScript
- javascript模擬實現ArrayList效果程式碼例項JavaScript
- JavaScript模擬HashMap類效果程式碼JavaScriptHashMap
- javascript模擬實現滾動條效果程式碼例項JavaScript
- javascript模擬實現連結的title效果例項程式碼JavaScript
- JavaScript模擬無重新整理評論效果JavaScript
- javascript模擬實現replaceAll()JavaScript
- js模擬實現列舉效果JS
- javascript瀑布流效果JavaScript
- javascript模擬new的實現JavaScript
- JavaScript 模擬new的實現JavaScript
- JavaScript模擬實現replaceAll方法JavaScript
- DataGuard模擬FailOver實驗AI
- javascript模擬美化select下拉選單效果詳解JavaScript
- JavaScript中模擬實現jsonpJavaScriptJSON
- 解除安裝oracleasm實驗模擬OracleASM
- js實現的模擬滾動條效果JS
- ds simulia suite 2022,流體模擬UI
- 純css模擬下雪效果CSS
- JavaScript專題之模擬實現newJavaScript
- JavaScript專題之模擬實現bindJavaScript
- javascript模擬實現函式過載JavaScript函式
- JavaScript深入之new的模擬實現JavaScript
- JavaScript深入之bind的模擬實現JavaScript
- JavaScript 深入之new的模擬實現JavaScript
- JavaScript 深入之bind的模擬實現JavaScript
- jquery模擬實現的連結title提示效果jQuery
- 模擬實現的星星評分效果詳解
- 分割槽儲存管理模擬實驗
- LInux實驗 : 程式排程模擬Linux
- 實驗三 程式模擬排程程式
- 實驗三 程式排程模擬程式
- ActiveMQ——基礎知識與模擬體驗MQ
- HTML5模擬齒輪動畫HTML動畫
- JavaScript 模擬 HashMap例子JavaScriptHashMap
- 模擬費用流小記
- javascript之模擬call以及apply實現JavaScriptAPP
- Tina-TI電路模擬初體驗(德州儀器電路模擬軟體)