Javascript 如何旋转<;画布>;,不是整个元素?
我现在正在尝试学习一些Javascript 如何旋转<;画布>;,不是整个元素?,javascript,css,html,canvas,rotation,Javascript,Css,Html,Canvas,Rotation,我现在正在尝试学习一些API。我的任务是创建一个简单的模拟式时钟,时钟指针可以工作(秒、分、时) 时钟框架、面和指针都使用相同的画布元素绘制。我创建了一个drawsecene()函数,它每秒运行一次,并重新绘制整个时钟。如果您想更深入地查看代码,我将把它发布到本文底部链接的jsbin中 目标是让drawScene()方法调用drawClockFace()方法,该方法将当前秒/分/小时传递给基于传入时间(即DrawSecond(currentSecond))绘制指针的单个函数 问题: 如何在不旋转
API。我的任务是创建一个简单的模拟式时钟,时钟指针可以工作(秒、分、时)
时钟框架、面和指针都使用相同的画布元素绘制。我创建了一个drawsecene()
函数,它每秒运行一次,并重新绘制整个时钟。如果您想更深入地查看代码,我将把它发布到本文底部链接的jsbin中
目标是让drawScene()
方法调用drawClockFace()
方法,该方法将当前秒/分/小时传递给基于传入时间(即DrawSecond(currentSecond)
)绘制指针的单个函数
问题:
如何在不旋转整个画布的情况下旋转画布的各个组件(即时钟上的秒针)?我知道我需要根据当前秒数计算从中心原点向外画线的位置。我只是不确定地质计算是否需要确定“在哪里”划界
这是我到目前为止所做的--注意它不是超干净的,因为我一直在使用它。
您可以使用context.save&context.restore临时旋转部分时钟(如秒针) 这个想法是:
- 保存未旋转的上下文:context.save()李>
- 旋转到所需角度:上下文。旋转(角度)李>
- 将上下文恢复到其未旋转状态,以便进一步绘制:context.restore()李>
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" />
<script src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: white; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
ctx.strokeStyle="black"
ctx.fillStyle="ivory";
function animate() {
requestAnimFrame(animate);
// clear the canvas
ctx.clearRect(0,0,canvas.width,canvas.height);
// Draw the clock face
ctx.beginPath();
ctx.arc(150,150,50,0,Math.PI*2);
ctx.closePath();
ctx.lineWidth=3;
ctx.stroke();
ctx.fillStyle="ivory";
ctx.fill();
ctx.fillStyle="black";
ctx.fillText("12",145,115);
// Separately rotate the second hand
// using ctx.save and ctx.restore
// plus ctx.rotate
// calc the rotation angle
var d=new Date();
var radianAngle=(d.getSeconds()/60)*Math.PI*2;
ctx.save();
ctx.translate(150,150);
ctx.rotate(radianAngle);
ctx.moveTo(0,0);
ctx.lineTo(45,0);
ctx.stroke();
ctx.restore();
}
animate();
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=350 height=350></canvas>
</body>
</html>
正文{背景色:白色;}
画布{边框:1px纯红;}
$(函数(){
var canvas=document.getElementById(“canvas”);
var ctx=canvas.getContext(“2d”);
ctx.strokeStyle=“黑色”
ctx.fillStyle=“象牙”;
函数animate(){
请求动画帧(动画);
//清理画布
clearRect(0,0,canvas.width,canvas.height);
//画钟面
ctx.beginPath();
ctx.arc(150150,50,0,数学PI*2);
ctx.closePath();
ctx.线宽=3;
ctx.stroke();
ctx.fillStyle=“象牙”;
ctx.fill();
ctx.fillStyle=“黑色”;
ctx.fillText(“12”,145115);
//分别旋转第二只手
//使用ctx.save和ctx.restore
//加上ctx
//计算旋转角度
var d=新日期();
var radianAngle=(d.getSeconds()/60)*Math.PI*2;
ctx.save();
翻译(150150);
旋转(弧度角);
ctx.moveTo(0,0);
ctx.lineTo(45,0);
ctx.stroke();
ctx.restore();
}
制作动画();
}); // end$(函数(){});
如何旋转画布的各个组件(例如,秒针)
在我的时钟上)而不旋转整个画布?
可以使用以下方法手动计算角度,而无需每次旋转画布。下面的演示使用毫秒生成一个平稳运行的时钟(如果不需要,我将在下面演示如何删除该时钟)
最初,您希望将画布旋转90度,使0度指向上,而不是向右。这使得角度方面的工作更容易,例如12点钟时产生0度。可以在绘制主面后进行此旋转
每只手:
- 基于时间获取它们的角度(本例中包含的毫秒用于平滑动画)
- 基于角度渲染线
(function loop() {
renderClock()
requestAnimationFrame(loop);
})();
如果您只想每秒更新,请将rAF替换为(您也可以从timeToAngles()
中删除计算,但在这种情况下它将是微观的):
然后根据从当前时间获得的角度渲染线:
function renderClock() {
var angles = timeToAngles(), /// get angles
cx = ctx.canvas.width * 0.5, /// center
cy = ctx.canvas.width * 0.5,
lh = cx * 0.5, /// length of hour's hand
lm = cx * 0.8, /// length of minute's hand
ls = cx * 0.9, /// length of second' hand
pos; /// end-point of hand
/// clear and render face
ctx.clearRect(0, 0, cx*2, cy*2);
ctx.beginPath();
ctx.arc(cx, cy, cx - ctx.lineWidth, 0, pi2);
/// hours
pos = lineToAngle(cx, cy, lh, angles.h);
ctx.moveTo(cx, cy);
ctx.lineTo(pos.x, pos.y);
/// minutes
pos = lineToAngle(cx, cy, lm, angles.m);
ctx.moveTo(cx, cy);
ctx.lineTo(pos.x, pos.y);
/// render hours and minutes
ctx.lineWidth = 5;
ctx.stroke();
ctx.beginPath();
/// seconds
pos = lineToAngle(cx, cy, ls, angles.s);
ctx.moveTo(cx, cy);
ctx.lineTo(pos.x, pos.y);
ctx.lineWidth = 2; /// create a variation for seconds hand
ctx.stroke();
}
此辅助函数基于角度和三角学计算终点:
function lineToAngle(x, y, length, angle) {
return {
x: x + length * Math.cos(angle),
y: y + length * Math.sin(angle)
}
}
渲染钟面的附加提示:
如果你正在制作一个时钟,那么这个技巧会非常有帮助——你可以在每次更新时,将画布转换为数据uri,并将其设置为画布(本身)的背景图像,而不是清除和渲染面
这样你只需要重新画手。将画布旋转90度之前(如上所示):
var dots=12,///每小时生成点
dotPos=cx*0.85,///点的位置
步长=pi2/点,///计算步长
a=0;///环路角度
ctx.beginPath();
///创建主体边框
ctx.beginPath();
ctx.弧(cx,cy,cx-ctx.lineWidth-2,0,pi2);
ctx.fillStyle='#000';
ctx.lineWidth=5;
ctx.stroke();
///时点颜色
ctx.fillStyle='#999';
///画点
对于(;a
然后在这里开始循环。答案太棒了。有学问的
function renderClock() {
var angles = timeToAngles(), /// get angles
cx = ctx.canvas.width * 0.5, /// center
cy = ctx.canvas.width * 0.5,
lh = cx * 0.5, /// length of hour's hand
lm = cx * 0.8, /// length of minute's hand
ls = cx * 0.9, /// length of second' hand
pos; /// end-point of hand
/// clear and render face
ctx.clearRect(0, 0, cx*2, cy*2);
ctx.beginPath();
ctx.arc(cx, cy, cx - ctx.lineWidth, 0, pi2);
/// hours
pos = lineToAngle(cx, cy, lh, angles.h);
ctx.moveTo(cx, cy);
ctx.lineTo(pos.x, pos.y);
/// minutes
pos = lineToAngle(cx, cy, lm, angles.m);
ctx.moveTo(cx, cy);
ctx.lineTo(pos.x, pos.y);
/// render hours and minutes
ctx.lineWidth = 5;
ctx.stroke();
ctx.beginPath();
/// seconds
pos = lineToAngle(cx, cy, ls, angles.s);
ctx.moveTo(cx, cy);
ctx.lineTo(pos.x, pos.y);
ctx.lineWidth = 2; /// create a variation for seconds hand
ctx.stroke();
}
function lineToAngle(x, y, length, angle) {
return {
x: x + length * Math.cos(angle),
y: y + length * Math.sin(angle)
}
}
var dots = 12, /// generate dots for each hour
dotPos = cx * 0.85, /// position of dots
step = pi2 / dots, /// calc step
a = 0; /// angle for loop
ctx.beginPath();
/// create body border
ctx.beginPath();
ctx.arc(cx, cy, cx - ctx.lineWidth - 2, 0, pi2);
ctx.fillStyle = '#000';
ctx.lineWidth = 5;
ctx.stroke();
/// color of hour dots
ctx.fillStyle = '#999';
/// draw the dots
for(; a < pi2; a += step) {
var pos = lineToAngle(cx, cy, dotPos, a);
ctx.beginPath();
ctx.arc(pos.x, pos.y, 3, 0, pi2);
ctx.fill();
}
/// create highlighted dots for every 3 hours
a = 0;
step = pi2 / 4;
ctx.fillStyle = '#777';
for(; a < pi2; a += step) {
var pos = lineToAngle(cx, cy, dotPos, a);
ctx.beginPath();
ctx.arc(pos.x, pos.y, 5, 0, pi2);
ctx.fill();
}
/// set as background
clock.style.backgroundImage = 'url(' + clock.toDataURL() + ')';