canvas绘制“海上升明月”

来源:互联网 发布:网络监控员是做什么的 编辑:程序博客网 时间:2024/04/28 02:03

核心内容

1.海浪绘制

海浪的形状有点像正弦函数,可以用canvas提供的三次贝赛尔曲线函数bezierCurveTo(x1,y1,x2,y2,x3,y3)

http://www.w3school.com.cn/tags/canvas_beziercurveto.asp

无论是arcTo还是二次贝赛尔曲线quadraticCurveTo,所谓的控制点就是切线的交点。海浪的动态效果通过改变控制点的纵坐标实现的。

2.升月绘制

升月包括两个部分:弯月和升起动画。
升起动画比较简单,改变弯月坐标,横坐标:radius * Math.cos(deg),纵坐标:radius * Math.sin(deg)。
弯月在于先用arc函数画外弧,再用arcTo画内弧,画内弧的时候需要选取弧外任意一点做控制点,然后通过相似三角形算出内弧半径即可。同时填充颜色。

源代码
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>海上生明月</title><style>html,body{margin: 0;padding: 0;width: 100%;height: 100%;overflow: hidden;}</style></head><body><canvas id="canvas"></canvas><script>var WINDOW_WIDTH;var WINDOW_HEIGHT;window.onload = function(){WINDOW_WIDTH = document.documentElement.clientWidth;WINDOW_HEIGHT = document.documentElement.clientHeight;var cvs = document.getElementById("canvas");cvs.width = WINDOW_WIDTH;cvs.height = WINDOW_HEIGHT;var ctx = cvs.getContext("2d");var offset = 0;var delta = 10;var deg = 0;var r = 1/5*WINDOW_WIDTH;setInterval(function(){offset += delta;if(Math.abs(offset)>150) {delta = -delta;offset += delta;}ctx.clearRect(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);//画个月亮消灭你if(Math.abs(deg)<90)deg--;var x = 1/2*WINDOW_WIDTH + Math.cos(deg/180*Math.PI)*r;var y = 1/4*WINDOW_HEIGHT + Math.sin(deg/180*Math.PI)*r;drawMoon(ctx, x, y, 45/360*Math.PI, 1, 180);//浪里个浪drawWave(ctx, offset);}, 50);};/** * 绘制海浪 * @param  {context} ctx     绘图上下文 * @param  {Number} offsetY 波峰偏移值 * @return {[type]}         [description] */function drawWave(ctx, offsetY){ctx.beginPath();var x = 0;var y = WINDOW_HEIGHT/2;var offsetX = 50;ctx.moveTo(x, y);for (var i = 0; i < 10; i++) {var delta = i * 4.5;ctx.bezierCurveTo(x+(1.5+delta)*offsetX, y+offsetY, x+(3+delta)*offsetX, y-offsetY, x+(4.5+delta)*offsetX, y);}ctx.lineTo(WINDOW_WIDTH, WINDOW_HEIGHT);ctx.lineTo(0, WINDOW_HEIGHT);ctx.closePath();ctx.fillStyle = "darkblue";ctx.fill();ctx.stroke();}/** * 绘制新月 * @param  {context} ctx 绘图上下文 * @param  {Number} xc  切线交点横坐标 * @return {[type]}     [description] */function createMoon(ctx, xc){//上圆弧切点var xa = 100;var ya = 100;//下圆弧切点var xb = 100;var yb = 200;//半圆半径var r = 50;//切线交点var yc = 150;ctx.beginPath();ctx.fillStyle="yellow";ctx.strokeStyle="yellow";//绘制半圆,一定要注意绘制路径ctx.arc((xa+xb)/2, (ya+yb)/2, r, 1/2*Math.PI, 3/2*Math.PI, true);var radius = r/(xc-xa)*Math.sqrt(Math.pow(r,2)+Math.pow(xc-xa,2));ctx.moveTo(xa, ya);ctx.arcTo(xc, yc, xb, yb, radius);ctx.fill();ctx.stroke();}/** * 绘制月亮 * @param  {context} ctx    上下文绘图环境 * @param  {Number} x      平移横坐标 * @param  {Number} y      平移纵坐标 * @param  {Number} rotate 旋转弧度 * @param  {Number} scale  缩放倍率 * @param  {Number} xc     切线交点横坐标 * @return {[type]}        [description] */function drawMoon(ctx, x, y, rotate, scale, xc){ctx.save();ctx.translate(x||0, y||0);ctx.rotate(rotate||0);ctx.scale(scale||1, scale||1);createMoon(ctx, xc);ctx.restore();}</script></body></html>


1 0