您的位置:首页 > Web前端 > JavaScript

JavaScript 雷达

2017-01-30 00:34 771 查看
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8">
<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="keywords" content="Orb trails">
<meta name="description" content="Orb trails">
<title>Orb trails</title>
<style>
body {
background: black;
color: #aaa;
font: 12px/20px helvetica, arial, sans-serif;
overflow: hidden;
}
#control-panel {
position: absolute;
padding: 10px;
border: 1px dotted Cornsilk;
border-radius: 10px;
background-color: rgba(0,0,0,.5);
}
#control-panel button {
margin: 5px 10px 5px 0;
width: 60px;
}
#control-panel input {
/* 添加这句后按钮和文字才会对齐 */
vertical-align:middle;
}
</style>
</head>
<body>
<div id="control-panel">
Click and drag to make more!
<br/>
<label>Direction: </label>
<input type="radio" name="direction" value="clockwise" checked/>Clockwise
<input type="radio" name="direction" value="counterclockwise">Counterclockwise
<br/>
<label>Angular Speed: </label>
<input type="radio" name="stepType" value="same" checked />Same
<input type="radio" name="stepType" value="random"/>Random
<br/>
<label>Trails: </label>
<input type="checkbox" id="trail" checked/>
<br/>
<button id="init">Init</button>
<button id="clear">Clear</button>
<button id="switchState">Pause</button>
<br/>
我在残酷的现实中反复挣扎,<br/>
残酷的现实却让我无法自拔。
</div>
<canvas id="canvas">Your browser can not support canvas</canvas>
<script>
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

var halfPI = Math.PI / 2;
var doublePI = Math.PI * 2;

//天体线条笔帽
var lineCap = "round";
//用来制作天体尾巴的蒙版透明度(透明度越低,尾巴越长)
var maskAlpha = 0.1;
//初始化的天体个数
var initCount = 30;
//每帧一次性更新和渲染的次数
var onceUpdateAndRenderTimes = 4;
//为了防止粒子被添加的太多,这里设置只有x或y的差值大于该阀值才能被添加
var offsetThreshold = 5;

//画布中心点坐标
var cx;
var cy;

//旋转方向[clockwise(顺时针), counterClockwise(逆时针)]
var direction = "clockwise";
//角速度步长[same(相同角速度), random(随机角速度)]
var stepType = "same";
//是否显示天体的尾巴
var isTrails = true;
//是否暂停
var isPause = false;

//天体粒子数组
var orbs = [];

//在[min,max]中随机选取一个数
function randomAtRange(obj) {
return Math.random() * (obj.max - obj.min) + obj.min;
}

//画线条
function strokeLine(x1, y1, x2, y2) {
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();
}

//天体粒子
var Orb = function(x, y) {
//宽度范围
var widthRange = {min: 1, max: 3};
//等角速度的时候的步长
var sameRadianStep = 0.01;
//随机角速度时候的步长
var randomRadianRange = {min: 0.005, max: 2 * sameRadianStep};

//上一次的位置
var lastX = x;
var lastY = y;
//与中心的距离(右下为正)
var dx = x - cx;
var dy = y - cy;
//距画布中心的半径
var radius = Math.sqrt(dx * dx + dy * dy);
//宽度
var width = randomAtRange(widthRange);
//每帧步长
var step = 0;
//Math.atan2(y,x)返回(-Math.PI,Math.PI], 返回(x,y)与0点钟方向的夹角, 顺时针方向为正。但由于画布是右下方为正,等价于做垂直镜像
var radian = Math.atan2(dx, dy);
//色相
var hue;

//绕中心旋转速度类型[same(等角速度)、random(随机)]
this.resetStepType = function() {
if(stepType === "same") {
step = sameRadianStep;
} else {
step = randomAtRange(randomRadianRange);
}
}

//判断当前点是否与给定点离的很近
this.isNear = function(pointX, pointY) {
if(Math.abs(pointX - x) < offsetThreshold && Math.abs(pointY - y) < offsetThreshold) {
return true;
}
return false;
}

//当画布大小被改变的时候
this.resetPos = function() {
x = lastX = cx + radius * Math.sin(radian);
y = lastY = cy + radius * Math.cos(radian);
}

this.update = function() {
lastX = x;
lastY = y;
x = cx + radius * Math.sin(radian);
y = cy + radius * Math.cos(radian);
hue = 360 * radian / doublePI;
if(direction === "clockwise") {
radian = (radian - step) % doublePI;
} else {
radian = (radian + step) % doublePI;
}
}

this.render = function() {
ctx.strokeStyle = "hsla(" + hue + ",100%,50%,1)";
ctx.lineWidth = width;
strokeLine(lastX, lastY, x, y);
}

this.resetStepType();
this.resetPos();
}

//初始化所有天体
function initOrbs() {
var len = Math.min(cx, cy);
var step = len / (initCount+1);
orbs = [];
for(var i=0, offsetY = cy - step; i<initCount; i++, offsetY -= step) {
orbs.push(new Orb(cx, offsetY));
}
}

function init() {
onResize();

var directionRadios = document.getElementsByName("direction");
var stepTypeRadios = document.getElementsByName("stepType");
var trailCb = document.getElementById("trail");
var initBtn = document.getElementById("init");
var clearBtn = document.getElementById("clear");
var switchStateBtn = document.getElementById("switchState");

window.addEventListener("resize", onResize);

//指定事件是否在捕获(true)或冒泡(false)阶段执行。true的触发顺序总是在false之前
canvas.addEventListener("mousedown", onMouseDown, false);
canvas.addEventListener("mouseup", onMouseUp, false);
canvas.addEventListener("mouseout", onMouseOut, false);

//旋转方向
for(var i=0; i<directionRadios.length; i++) {
//这里用change或者click事件均可以
directionRadios[i].addEventListener("change", function(){
direction = event.target.value;
});
}
//角速度类型
for(var i=0; i<stepTypeRadios.length; i++) {
//这里用change或者click事件均可以
stepTypeRadios[i].addEventListener("change", function(){
stepType = event.target.value;
for(var i=0; i<orbs.length; i++) {
orbs[i].resetStepType();
}
});
}

//是否显示轨迹
trailCb.addEventListener("change", function() {
isTrails = event.target.checked;
});
//清除所有天体
clearBtn.addEventListener("click", function() {
orbs = [];
//这里还要清除一下画布,否则上面还有颜色残留,只是用某个透明度的黑覆盖而已
ctx.clearRect(0, 0, canvas.width, canvas.height);
});
//初始化一部分的天体
initBtn.addEventListener("click", initOrbs);
//切换天体的运行和停止状态
switchStateBtn.addEventListener("click", function() {
isPause = !isPause;
console.log(isPause);
switchStateBtn.innerHTML = isPause ? "Pause" : "Start";
});

ctx.lineCap = lineCap;
initOrbs();
loop();
}

function loop() {
if(!isPause) {
if(isTrails) {
//使用带透明度的颜色来填充就相当于色彩叠加了
ctx.fillStyle = "rgba(0,0,0," + maskAlpha + ")";
ctx.fillRect(0, 0, canvas.width, canvas.height);
} else {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
for(var i=0; i<orbs.length; i++) {
for(var j=0; j<onceUpdateAndRenderTimes; j++) {
orbs[i].update();
orbs[i].render();
}
}
}
requestAnimationFrame(loop);
}

//有一个瑕疵是暂停的话,然后resize,所有的点都会消失
function onResize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
cx = canvas.width / 2;
cy = canvas.height / 2;
for(var i=0; i<orbs.length; i++) {
orbs[i].resetPos();
}
}

function onMouseDown() {
canvas.addEventListener("mousemove", onMouseMove);
onMouseMove();
}

function onMouseMove() {
//event.offsetX 等价于 event.pageX - canvas.offsetLeft
var x = event.offsetX;
var y = event.offsetY;
for(var i=0; i<orbs.length; i++) {
if(orbs[i].isNear(x, y)) {
return;
}
}
orbs.push(new Orb(x, y));
}

function onMouseUp() {
canvas.removeEventListener("mousemove", onMouseMove);
}

function onMouseOut() {
canvas.removeEventListener("mousemove", onMouseMove);
}

init();
</script>
</body>
</html>


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  javascript canvas