老师,您好,我想把您第一节课讲的倒计时的例子中的“圆形”换为“笛卡尔心形线”,我只需要修改绘制“圆形”的方法就OK了,但是怎么绘制“笛卡尔心形线”,主要是坐标值不知道如何使用。求指教
这个我换了,没有效果
把画出小球的代码换成我给你的心型公式 这都不理解我就服了你了
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
<meta charset="utf-8" />
<style type="text/css">
.container {
padding: 0px;
margin: 0px;
width: 100%;
text-align: center;
}
.countdown {
border: 1px solid #ccc;
}
</style>
<script type="text/javascript" src="js/digit.js"></script>
</head>
<body>
<div id="container" class="container">
<canvas id="countdown" class="countdown" width="1400" height="700"></canvas>
</div>
<script>
function Clock(targetId, countTime) {
var canvas = document.getElementById(targetId);
var ctx = canvas.getContext("2d");
var width = canvas.width;
var height = canvas.height;
var scale = width / 1400;
var now = new Date();
var endTime = countTime;
var balls = [];
var ballMax = 500;
var last_hour;
var last_minute;
var last_second;
function drawDigit(left, top, num, size, color, pushBall) {
var number = digit[num];
var dotScale = num === 10 ? size / 72 : size / 126;
var dotRadius = 8 * dotScale;
var dotPadding = 1 * dotScale;
var dotSize = 2 * (dotRadius + dotPadding);
ctx.save();
ctx.fillStyle = color;
var row = number.length;
for (var i = 0; i < row; i++) {
var col = number[i].length;
for (var j = 0; j < col; j++) {
var value = number[i][j];
if (value === 1) {
var x = (j + 0.5) * dotSize + left;
var y = (i + 0.5) * dotSize + top;
ctx.beginPath();
ctx.moveTo(x, y);
ctx.arc(x, y, dotRadius, 0, 2 * Math.PI, false);
if (pushBall === true) {
balls.push(Ball(x, y, Math.random() * 8 * scale - 4 * scale, Math.random() * -5 * scale, dotRadius, 2 * scale, 0.8));
}
ctx.fill();
}
}
}
ctx.restore();
}
const colors = ["#33B5E5", "#0099CC", "#AA66CC", "#9933CC", "#99CC00", "#669900", "#FFBB33", "#FF8800", "#FF4444", "#CC0000"]
function Ball(x, y, vx, vy, r, g, k) {
var start_x = x;
var start_y = y;
var end_x;
var end_y;
var start_v_x = vx;
var start_v_y = vy;
var end_v_x;
var end_v_y;
var r = r; //小球半径
var g = g; //重力加速度
var k = k; //弹性系数
var interval = 1; //时间间隔 相当于调整速度快慢
var color = colors[Math.floor(Math.random() * colors.length)];
var dead = false;
return {
isDead: function () { return dead },
draw: function () {
end_v_x = start_v_x;
end_v_y = start_v_y + interval * g;
end_x = start_x + 0.5 * (start_v_x + end_v_x) * interval;
end_y = start_y + 0.5 * (start_v_y + end_v_y) * interval;
if (end_y + r > height) {
//求根公式求出小球起始位置到落地时间
var param = Math.pow(2 * start_v_y, 2) + 8 * g * (height - start_y - r);
var t1 = (-2 * start_v_y + Math.pow(param, 0.5)) / (2 * g);
var t2 = (-2 * start_v_y - Math.pow(param, 0.5)) / (2 * g);
var pt = t1 > 0 ? t1 : t2;
collision_v_y = -(start_v_y + pt * g) * k;
end_v_y = collision_v_y + (interval - pt) * g;
end_y = height - r + 0.5 * (collision_v_y + end_v_y) * (interval - pt);
}
//弹性势能小于重力势能小球平稳着地
if (end_y + r > height) {
end_y = height - r;
end_v_y = 0;
g = 0;
}
if ((end_x < 0) || (end_x > width)) {
dead = true;
}
//重新定义起点和初始速度
start_x = end_x;
start_y = end_y;
start_v_x = end_v_x;
start_v_y = end_v_y;
//画出小球
ctx.save();
ctx.beginPath();
ctx.fillStyle = color;
ctx.moveTo(end_x, end_y);
ctx.arc(end_x, end_y, r, 0, 2 * Math.PI, false);
ctx.fill();
ctx.restore();
}
}
}
function cleanScreen() {
ctx.clearRect(0, 0, width, height);
}
function drawClock(x, y, difference, style) {
var digitSize = 126 * scale;
var colonSize = 72 * scale;
var margin = 18 * scale;
var hour = Math.floor(difference / 3600000) % 24;
var minute = Math.floor(difference / 60000) % 60;
var second = Math.floor(difference / 1000) % 60;
//时
drawDigit(x, y, Math.floor(hour / 10), digitSize, style,
Math.floor(last_hour / 10) !== Math.floor(hour / 10));
drawDigit(x + digitSize + margin, y, hour % 10, digitSize, style,
last_hour % 10 !== hour % 10);
//分
drawDigit(x + 2 * digitSize + 2 * margin, y, 10, colonSize, style);
drawDigit(x + 2 * digitSize + 3 * margin + colonSize, y, Math.floor(minute / 10), digitSize, style,
Math.floor(last_minute / 10) !== Math.floor(minute / 10));
drawDigit(x + 3 * digitSize + 4 * margin + colonSize, y, minute % 10, digitSize, style,
last_minute % 10 !== minute % 10);
//秒
drawDigit(x + 4 * digitSize + 5 * margin + colonSize, y, 10, colonSize, style);
drawDigit(x + 4 * digitSize + 6 * margin + 2 * colonSize, y, Math.floor(second / 10), digitSize, style,
Math.floor(last_second / 10) !== Math.floor(second / 10));
drawDigit(x + 5 * digitSize + 7 * margin + 2 * colonSize, y, second % 10, digitSize, style,
last_second % 10 !== second % 10);
last_second = second;
last_minute = minute;
last_hour = hour;
}
return {
draw: function draw() {
var difference = endTime.getTime() - new Date().getTime();
cleanScreen();
drawClock(188 * scale, 50 * scale, difference, "rgb(0, 102, 153)");
if (balls.length > ballMax) {
balls.splice(0, balls.length - ballMax);
}
balls.forEach(function (ball, index) {
ball.draw();
});
}
}
}
var date = new Date();
//倒计时1小时
date.setTime(date.getTime() + 1000 * 60 * 60 * 1);
var clock = Clock("countdown", date);
setInterval(function () { clock.draw(); }, 50);
</script>
</body>
</html>
球的方法可以这么解
var ballMax = 500;
if (balls.length > ballMax) {
balls.splice(0, balls.length - ballMax);
}
就是球超过了最大数 就把这个数组中的前一部分去掉
看着挺好玩的我就写了个demo可以运行希望能帮到你
function drawCardioid(x, y, w, h, p) {
p = p || 100;
ctx.save();
ctx.translate(x, y);
for (var i = -p; i <= p; i++) {
var y1 = Math.pow(1 - Math.pow(i / p, 2), 0.5) + Math.pow(Math.pow(i / p, 2), 1 / 3);
if (i == -p) {
ctx.moveTo(i / p * w * 0.5, -y1 * h * 0.5 * 0.8);
} else {
ctx.lineTo(i / p * w * 0.5, -y1 * h * 0.5 * 0.8);
};
};
for (var i = p; i >= -p; i--) {
var y2 = -Math.pow(1 - Math.pow(i / p, 2), 0.5) + Math.pow(Math.pow(i / p, 2), 1 / 3);
ctx.lineTo(i / p * w * 0.5, -y2 * h * 0.5 * 0.8);
};
ctx.closePath();
ctx.stroke();
};