Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/css/35.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/actionscript-3/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何旋转<;画布>;,不是整个元素?_Javascript_Css_Html_Canvas_Rotation - Fatal编程技术网

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() + ')';